题目大意:维护一个环,每个点有一个颜色,提供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 );
}
}
}
}