题目大意:维护一个环,每个点有一个颜色,提供6种操作:
1.将这个环顺时针旋转k
2.沿点1所在直径翻转
3.将两个珠子互换
4.将一段区间染色
5.查询这个环上有多少颜色段
6.查询一段区间有多少颜色段
关于颜色段通用的处理方法是每个区间记录三个值,颜色段数、左端点颜色、右端点颜色,合并时颜色段数相加,如果左区间右端点和右区间左端点颜色相同则减一
然后用Splay维护区间即可 不过这题还是有一些小细节需要处理
首先null节点要保证不会被修改 然后更新的时候特判 如果一段区间颜色是0直接返回另一区间即可
翻转时要把2~n翻转 不能翻转1~n
互换时直接交换必死 因为两个节点上面可能会有标记 正确的做法是把两个节点都旋转上来,这样保证没有标记 然后交换颜色并维护即可
询问环上的颜色段时直接cnt-(lcolor==rcolor)就挂了 因为当整个环都是同种颜色的时候前面那个表达式等于0 所以要特判等于0的时候输出1
写这题时候各种脑残,旋转不换根,Find函数传参传的0,写完都做好测数据的准备了,结果交上1A。。。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; struct color_segment{ int cnt,lcolor,rcolor; color_segment(int x) { cnt=1; if(!x) cnt=0; lcolor=rcolor=x; } }; color_segment operator + (const color_segment x,const color_segment y) { color_segment re(0); re.lcolor=x.lcolor?x.lcolor:y.lcolor; re.rcolor=y.rcolor?y.rcolor:x.rcolor; re.cnt=x.cnt+y.cnt-(x.rcolor==y.lcolor); return re; } struct abcd{ int num,siz; abcd *fa,*ls,*rs; color_segment *s; int rev_mark,change_mark; abcd(int x); void Push_Up(); void Push_Down(); }*null=new abcd(0),*root=null; abcd :: abcd(int x) { num=x; siz=1; if(!x) siz=0; fa=ls=rs=null; rev_mark=change_mark=0; s=new color_segment(x); } void abcd :: Push_Up() { siz=ls->siz+rs->siz+1; *s=(*ls->s)+color_segment(num)+(*rs->s); } void abcd :: Push_Down() { if(rev_mark) { ls->rev_mark^=1; rs->rev_mark^=1; swap(ls->ls,ls->rs); swap(rs->ls,rs->rs); swap(ls->s->lcolor,ls->s->rcolor); swap(rs->s->lcolor,rs->s->rcolor); rev_mark=0; } if(change_mark) { if(ls!=null) { ls->num=ls->change_mark=change_mark; *ls->s=color_segment(change_mark); } if(rs!=null) { rs->num=rs->change_mark=change_mark; *rs->s=color_segment(change_mark); } change_mark=0; } } void Zig(abcd *x) { abcd *y=x->fa; y->Push_Down(); x->Push_Down(); y->ls=x->rs; x->rs->fa=y; x->rs=y; x->fa=y->fa; if(y==y->fa->ls) y->fa->ls=x; else if(y==y->fa->rs) y->fa->rs=x; y->fa=x; y->Push_Up(); if(y==root) root=x; } void Zag(abcd *x) { abcd *y=x->fa; y->Push_Down(); x->Push_Down(); y->rs=x->ls; x->ls->fa=y; x->ls=y; x->fa=y->fa; if(y==y->fa->ls) y->fa->ls=x; else if(y==y->fa->rs) y->fa->rs=x; y->fa=x; y->Push_Up(); if(y==root) root=x; } void Splay(abcd *x,abcd *Tar) { while(1) { abcd *y=x->fa,*z=y->fa; if(y==Tar) break; if(z==Tar) { if(x==y->ls) Zig(x); else Zag(x); break; } if(x==y->ls) { if(y==z->ls) Zig(y); Zig(x); } else { if(y==z->rs) Zag(y); Zag(x); } } x->Push_Up(); } void Find(abcd *x,int y,abcd *z) { while(1) { x->Push_Down(); if(y<=x->ls->siz) x=x->ls; else { y-=x->ls->siz; if(y==1) break; y--; x=x->rs; } } Splay(x,z); } void Insert(abcd *&x,int y,abcd *z) { if(x==null) { x=new abcd(y); x->fa=z; Splay(x,null); return ; } x->Push_Down(); Insert(x->rs,y,x); } int n,m,c; int main() { int i,x,y,z; char p[10]; cin>>n>>c; Insert(root,19980402,null); for(i=1;i<=n;i++) scanf("%d",&x),Insert(root,x,null); Insert(root,19980402,null); cin>>m; for(i=1;i<=m;i++) { scanf("%s",p); if(p[0]=='R') { scanf("%d",&x); Find(root,n-x+1,null); Find(root,n+2,root); abcd *temp=root->rs->ls; root->rs->ls=null; root->rs->Push_Up(); root->Push_Up(); Find(root,1,null); Find(root,2,root); root->rs->ls=temp; temp->fa=root->rs; root->rs->Push_Up(); root->Push_Up(); } else if(p[0]=='F') { Find(root,2,null); Find(root,n+2,root); abcd *temp=root->rs->ls; temp->rev_mark^=1; swap(temp->ls,temp->rs); swap(temp->s->lcolor,temp->s->rcolor); } else if(p[0]=='S') { scanf("%d%d",&x,&y); if(x==y) continue; if(x>y) swap(x,y); Find(root,x+1,null); Find(root,y+1,root); swap(root->rs->num,root->num); root->rs->Push_Up(); root->Push_Up(); } else if(p[0]=='P') { scanf("%d%d%d",&x,&y,&z); if(x<=y) { Find(root,x,null); Find(root,y+2,root); abcd *temp=root->rs->ls; temp->num=temp->change_mark=z; *temp->s=color_segment(z); } else { Find(root,x,null); Find(root,n+2,root); abcd *temp=root->rs->ls; temp->num=temp->change_mark=z; *temp->s=color_segment(z); Find(root,1,null); Find(root,y+2,root); temp=root->rs->ls; temp->num=temp->change_mark=z; *temp->s=color_segment(z); } } else if(p[0]=='C'&&p[1]==0) { Find(root,1,null); Find(root,n+2,root); abcd *temp=root->rs->ls; z=temp->s->cnt-(temp->s->lcolor==temp->s->rcolor); if(!z)++z; printf("%d\n",z); } else{ scanf("%d%d",&x,&y); if(x<=y) { Find(root,x,null); Find(root,y+2,root); abcd *temp=root->rs->ls; printf("%d\n",temp->s->cnt); } else { Find(root,x,null); Find(root,n+2,root); abcd *temp=root->rs->ls; color_segment s=*temp->s; Find(root,1,null); Find(root,y+2,root); temp=root->rs->ls; s=s+*temp->s; printf("%d\n", s.cnt ); } } } }