传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1493
题解:这道题如果没有旋转和翻转的话,那这就是一道裸的线段树了,所以就可以想,如何将旋转和翻转过滤掉,使它真正成为一道线段树的傻逼题。
因为无论如何旋转或是翻转,都不会影响这条项链的位置变化,所以我们可以考虑记录初始时位于位置1的珠子在经过变换后的位置,和这个项链是否经过翻转,这样就可以在每次修改或查询时,从现在的位置推算出这个位置的珠子原来的位置,之后在线段树上进行查询和修改即可。
虽然很好想,但是做起来很麻烦,一大堆的小细节TvT
Code
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 500010
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
struct node
{
int l,r,sum;
};
node f[N<<2];
int n,m,q,t;
bool k;
int lazy[N<<2];
void PushUp(node l,node r,node &rt)
{
rt.l=l.l,rt.r=r.r,rt.sum=l.sum+r.sum;
if(l.r==r.l)rt.sum--;
}
void PushDown(int rt)
{
if(lazy[rt])
{
lazy[ls]=lazy[rs]=lazy[rt];
f[ls].l=f[rs].l=f[ls].r=f[rs].r=lazy[rt];
f[ls].sum=f[rs].sum=1;
lazy[rt]=0;
}
}
void build(int l,int r,int rt)
{
if(l==r)
{
scanf("%d",&f[rt].l);
f[rt].r=f[rt].l;
f[rt].sum=1;
return ;
}
int mid=(l+r)>>1;
build(lson);
build(rson);
PushUp(f[ls],f[rs],f[rt]);
}
void updata(int l,int r,int rt,int L,int R,int c)
{
if(l>=L&&r<=R)
{
f[rt].l=f[rt].r=c;
f[rt].sum=1;
lazy[rt]=c;
return ;
}
PushDown(rt);
int mid=(l+r)>>1;
if(mid>=L)updata(lson,L,R,c);
if(mid<R)updata(rson,L,R,c);
PushUp(f[ls],f[rs],f[rt]);
}
node query(int l,int r,int rt,int L,int R)
{
if(l>=L&&r<=R)return f[rt];
PushDown(rt);
int mid=(l+r)>>1;
node a1,a2,a;
if(mid>=L&&mid>=R)return query(lson,L,R);
if(mid<R&&mid<L)return query(rson,L,R);
if(mid>=L&&mid<R)
{
a1=query(lson,L,R);
a2=query(rson,L,R);
PushUp(a1,a2,a);
}
return a;
}
void doing(int &x,int &y)
{
if(!k)
{
if(x>=t+1)x=x-t;
else x=n-t+x;
if(y>=t+1)y=y-t;
else y=n-t+y;
}else
{
if(x<=t+1)x=t-x+2;
else x=t+n-x+2;
if(y<=t+1)y=t-y+2;
else y=t+n-y+2;
}
}
int main()
{
cin>>n>>m;
build(1,n,1);
cin>>q;
for(int i=1;i<=q;i++)
{
int x,y,z;
char s[10];
scanf("%s",s);
if(s[0]=='R')
{
scanf("%d",&x);
t=(t+x)%n;
}else if(s[0]=='F')
{
k=!k;
t=(n-t)%n;
}else if(s[0]=='S')
{
scanf("%d%d",&x,&y);
doing(x,y);
node a1=query(1,n,1,x,x);
node a2=query(1,n,1,y,y);
updata(1,n,1,x,x,a2.l);
updata(1,n,1,y,y,a1.l);
}else if(s[0]=='P')
{
scanf("%d%d%d",&x,&y,&z);
doing(x,y);
if(k)swap(x,y);
if(x<=y)updata(1,n,1,x,y,z);
else updata(1,n,1,x,n,z),updata(1,n,1,1,y,z);
}else if(s[0]=='C'&&s[1]!='S')
{
int p=f[1].sum;
if(f[1].l==f[1].r)p--;
if(p)printf("%d\n",p);
else puts("1");
}else
{
scanf("%d%d",&x,&y);
doing(x,y);
node s1,s2,p;
if(k)swap(x,y);
if(x<=y)p=query(1,n,1,x,y);
else{
s1=query(1,n,1,x,n);
s2=query(1,n,1,1,y);
if(k)
{
swap(s1.l,s1.r);
swap(s2.l,s2.r);
swap(s1,s2);
}
PushUp(s1,s2,p);
}
printf("%d\n",p.sum);
}
}
return 0;
}