题目描述
题解
好久没写数据结构了
维护size、有几段sum、最左边和最右边的颜色lc和rc
需要注意的几个地方:
1、因为在开始和结尾插入了点,注意find的编号问题
2、所有标记都是对当前点已经做过但是对儿子并没有做过
3、交换的时候要同时交换lc和rc
4、提取区间之后要将根的右儿子和根都update
5、rotate和find的时候不要忘了update和pushdown
6、如果一个环只有一种颜色需要特判,也就是ans=max(ans,1)
代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
#define N 500005
int n,c,root,q,k,l,r,x,ans;
char opt[5];
int f[N],ch[N][2],color[N],size[N],lc[N],rc[N],sum[N],rev[N],delta[N];
void update(int x)
{
size[x]=1;
lc[x]=rc[x]=color[x];
sum[x]=1;
if (ch[x][0])
{
size[x]+=size[ch[x][0]];
lc[x]=lc[ch[x][0]];
sum[x]+=sum[ch[x][0]];
if (rc[ch[x][0]]==color[x]) --sum[x];
}
if (ch[x][1])
{
size[x]+=size[ch[x][1]];
rc[x]=rc[ch[x][1]];
sum[x]+=sum[ch[x][1]];
if (lc[ch[x][1]]==color[x]) --sum[x];
}
}
void pushdown(int x)
{
int l=ch[x][0],r=ch[x][1];
if (rev[x])
{
if (l)
{
rev[l]^=1;
swap(ch[l][0],ch[l][1]);
swap(lc[l],rc[l]);
}
if (r)
{
rev[r]^=1;
swap(ch[r][0],ch[r][1]);
swap(lc[r],rc[r]);
}
rev[x]=0;
}
if (delta[x])
{
if (l) color[l]=lc[l]=rc[l]=delta[l]=delta[x],sum[l]=1;
if (r) color[r]=lc[r]=rc[r]=delta[r]=delta[x],sum[r]=1;
delta[x]=0;
}
}
int build(int l,int r,int fa)
{
if (l>r) return 0;
int mid=(l+r)>>1;
f[mid]=fa;
int ls=build(l,mid-1,mid);
int rs=build(mid+1,r,mid);
ch[mid][0]=ls,ch[mid][1]=rs;
update(mid);
return mid;
}
int get(int x)
{
return ch[f[x]][1]==x;
}
void rotate(int x)
{
int old=f[x],oldf=f[old],wh=get(x);
pushdown(old);
pushdown(x);
ch[old][wh]=ch[x][wh^1];
if (ch[old][wh]) f[ch[old][wh]]=old;
ch[x][wh^1]=old;
f[old]=x;
if (oldf) ch[oldf][ch[oldf][1]==old]=x;
f[x]=oldf;
update(old);
update(x);
}
void splay(int x,int tar)
{
for (int fa;(fa=f[x])!=tar;rotate(x))
if (f[fa]!=tar)
rotate((get(x)==get(fa))?fa:x);
if (!tar) root=x;
}
int find(int x)
{
int now=root;
while (1)
{
pushdown(now);
if (ch[now][0]&&size[ch[now][0]]>=x) now=ch[now][0];
else
{
int tmp=(ch[now][0])?size[ch[now][0]]:0;
++tmp;
if (x<=tmp) return now;
x-=tmp;
now=ch[now][1];
}
}
}
int main()
{
scanf("%d%d",&n,&c);
for (int i=2;i<=n+1;++i) scanf("%d",&color[i]);
color[1]=color[n+2]=c+1;
root=build(1,n+2,0);
scanf("%d",&q);
while (q--)
{
scanf("%s",opt);
if (opt[0]=='R')
{
scanf("%d",&k);
// n-k+1 n
int aa=find(n-k+1);
int bb=find(n+2);
splay(aa,0);
splay(bb,aa);
int now=ch[ch[root][1]][0];
ch[ch[root][1]][0]=0;
update(ch[root][1]);
update(root);
// 0 1
int cc=find(1);
int dd=find(2);
splay(cc,0);
splay(dd,cc);
ch[ch[root][1]][0]=now;
f[now]=ch[root][1];
update(ch[root][1]);
update(root);
}
if (opt[0]=='F')
{
if (n<=2) continue;
// 2 n
int aa=find(2);
int bb=find(n+2);
splay(aa,0);
splay(bb,aa);
int now=ch[ch[root][1]][0];
swap(ch[now][0],ch[now][1]);
swap(lc[now],rc[now]);
rev[now]^=1;
}
if (opt[0]=='S')
{
scanf("%d%d",&l,&r);
int aa=find(l+1);
int bb=find(r+1);
swap(color[aa],color[bb]);
splay(aa,0);
splay(bb,0);
}
if (opt[0]=='P')
{
scanf("%d%d%d",&l,&r,&x);
if (l<=r)
{
// l r
int aa=find(l);
int bb=find(r+2);
splay(aa,0);
splay(bb,aa);
int now=ch[ch[root][1]][0];
color[now]=lc[now]=rc[now]=x;
sum[now]=1;
delta[now]=x;
update(ch[root][1]);
update(root);
}
else
{
// l n
int aa=find(l);
int bb=find(n+2);
splay(aa,0);
splay(bb,aa);
int now=ch[ch[root][1]][0];
color[now]=lc[now]=rc[now]=x;
sum[now]=1;
delta[now]=x;
update(ch[root][1]);
update(root);
// 1 r
int cc=find(1);
int dd=find(r+2);
splay(cc,0);
splay(dd,cc);
now=ch[ch[root][1]][0];
color[now]=lc[now]=rc[now]=x;
sum[now]=1;
delta[now]=x;
update(ch[root][1]);
update(root);
}
}
if (opt[0]=='C')
if (opt[1]=='S')
{
scanf("%d%d",&l,&r);
if (l<=r)
{
// l r
int aa=find(l);
int bb=find(r+2);
splay(aa,0);
splay(bb,aa);
int now=ch[ch[root][1]][0];
ans=sum[now];
if (l==1&&r==n&&lc[now]==rc[now]) --ans;
ans=max(ans,1);
printf("%d\n",ans);
}
else
{
// l n
int aa=find(l);
int bb=find(n+2);
splay(aa,0);
splay(bb,aa);
ans=sum[ch[ch[root][1]][0]];
// 1 r
int cc=find(1);
int dd=find(r+2);
splay(cc,0);
splay(dd,cc);
ans+=sum[ch[ch[root][1]][0]];
// 1 n
int ee=find(2);
int ff=find(n+1);
if (color[ee]==color[ff]) --ans;
ans=max(ans,1);
printf("%d\n",ans);
}
}
else
{
int aa=find(1);
int bb=find(n+2);
splay(aa,0);
splay(bb,aa);
int now=ch[ch[root][1]][0];
ans=sum[now];
if (lc[now]==rc[now]) --ans;
ans=max(ans,1);
printf("%d\n",ans);
}
}
return 0;
}