真™恶心,代码题就是痛苦
我的想法是先双倍展开后线段树维护,双倍展开后Print和Swap的操作对于前后两边都要做一次,调了半天
前两个操作可以不动线段树而把他询问的坐标转化到正确坐标即可
代码 :
#include<bits/stdc++.h> using namespace std; #define MAXN 500005 int n,c,cl[MAXN*2]; int q,Tf,Tv; char qe[4]; inline int Tran(int x) {return Tf?((n-(x+Tv))%n+n)%n:(x+Tv)%n;} namespace SegmentTree{ const int L=0,R=1; struct node{ int son[2],be,nd,cs,set; }x[MAXN*4]; int sz=1; inline void updata(int num) { x[num].be=x[x[num].son[L]].be; x[num].nd=x[x[num].son[R]].nd; x[num].cs=x[x[num].son[L]].cs+x[x[num].son[R]].cs; if(x[x[num].son[L]].nd==x[x[num].son[R]].be) x[num].cs--; } inline void Set(int num,int tc) { x[num].be=x[num].nd=x[num].set=tc;x[num].cs=1; } inline void maintain(int num) { Set(x[num].son[L],x[num].set); Set(x[num].son[R],x[num].set); x[num].set=0; } node Merge(node a,node b) { node ret; ret.be=a.be;ret.nd=b.nd; ret.cs=a.cs+b.cs; if(a.nd==b.be) ret.cs--; return ret; } void _init(int l,int r,int num) { if(l==r) { x[num].be=x[num].nd=cl[l]; x[num].cs=1;return; } int mid=l+r>>1; x[num].son[L]=++sz;x[num].son[R]=++sz; _init(l,mid,x[num].son[L]);_init(mid+1,r,x[num].son[R]); updata(num); } void Print(int l,int r,int nl,int nr,int num,int tc) { if(l==nl&&r==nr) {Set(num,tc);return;} int mid=l+r>>1; if(x[num].set) maintain(num); if(nl>mid) Print(mid+1,r,nl,nr,x[num].son[R],tc); else if(nr<=mid) Print(l,mid,nl,nr,x[num].son[L],tc); else { Print(l,mid,nl,mid,x[num].son[L],tc); Print(mid+1,r,mid+1,nr,x[num].son[R],tc); } updata(num); } node TQurey(int l,int r,int nl,int nr,int num) { if(l==nl&&r==nr) return x[num]; int mid=l+r>>1;node ret; if(nl>mid) ret=TQurey(mid+1,r,nl,nr,x[num].son[R]); else if(nr<=mid) ret=TQurey(l,mid,nl,nr,x[num].son[L]); else ret=Merge(TQurey(l,mid,nl,mid,x[num].son[L]),TQurey(mid+1,r,mid+1,nr,x[num].son[R])); if(x[num].set) {ret.be=ret.nd=x[num].set;ret.cs=1;} return ret; } int TColor(int p,int l,int r,int num) { if(l==r) return x[num].be; if(x[num].set) return x[num].set; int mid=l+r>>1; if(p>mid) return TColor(p,mid+1,r,x[num].son[R]); else return TColor(p,l,mid,x[num].son[L]); } inline int Qurey(int l,int r,bool cr) { if(l>r) swap(l,r); node ans=TQurey(0,2*n-1,l,r,1); if(cr&&ans.be==ans.nd&&ans.cs>1) ans.cs--; return ans.cs; } inline int Color(int p) { return TColor(p,0,2*n-1,1); } } #define ST SegmentTree int main() { scanf("%d%d",&n,&c); for(int i=0;i<n;i++) scanf("%d",&cl[i]); for(int i=0;i<n;i++) cl[n+i]=cl[i]; ST::_init(0,(n<<1)-1,1); scanf("%d",&q); for(int a,b,c,i=1;i<=q;i++) { scanf("%s",qe); if(qe[0]=='R') {scanf("%d",&a);Tv=((Tv-a)%n+n)%n;} else if(qe[0]=='F') {Tf^=1;Tv=((-Tv)%n+n)%n;} else if(qe[0]=='C') { if(qe[1]=='S') { scanf("%d%d",&a,&b);a--;b--; a=Tran(a);b=Tran(b);if(Tf) swap(a,b); if(b<a) b+=n; printf("%d ",ST::Qurey(a,b,0)); } else printf("%d ",ST::Qurey(0,n-1,1)); } else if(qe[0]=='P') { scanf("%d%d%d",&a,&b,&c);a--;b--; a=Tran(a);b=Tran(b);if(Tf) swap(a,b); if(b<a) b+=n; ST::Print(0,2*n-1,a,b,1,c); if(b+n<2*n) ST::Print(0,2*n-1,a+n,b+n,1,c); else { ST::Print(0,2*n-1,a+n,2*n-1,1,c); ST::Print(0,2*n-1,0,(b+n)%n,1,c); } } else if(qe[0]=='S') { scanf("%d%d",&a,&b);a--;b--; a=Tran(a);b=Tran(b); int t1=ST::Color(a),t2=ST::Color(b); ST::Print(0,2*n-1,a,a,1,t2);if(a+n<2*n) ST::Print(0,2*n-1,a+n,a+n,1,t2); ST::Print(0,2*n-1,b,b,1,t1);if(b+n<2*n) ST::Print(0,2*n-1,b+n,b+n,1,t1); } /* for(int i=0;i<2*n;i++) { printf("%d ",ST::Color(Tran(i))); } cout<<endl; */ } return 0; } #undef ST /* 7 4 1 3 3 3 3 1 1 100 F R 2 P 1 7 1 */