Description
T公司是一家专门生产彩色珠子项链的公司,其生产的项链设计新颖、款式多样、价格适中,广受青年人的喜爱。最近T公司打算推出一款项链自助生产系统,使用该系统顾客可以自行设计心目中的美丽项链。该项链自助生产系统包括硬件系统与软件系统,软件系统与用户进行交互并控制硬件系统,硬件系统接受软件系统的命令生产指定的项链。该系统的硬件系统已经完成,而软件系统尚未开发,T公司的人找到了正在参加全国信息学竞赛的你,你能帮助T公司编写一个软件模拟系统吗?一条项链包含 N 个珠子,每个珠子的颜色是 1,2,…,c 中的一种。项链被固定在一个平板上,平板的某个位置被标记位置 1 ,按顺时针方向其他位置被记为 2,3,…,N。
你将要编写的软件系统应支持如下命令:
Input
输入文件第一行包含两个整数 N,c ,分别表示项链包含的珠子数目以及颜色数目。
第二行包含 N 个整数,x1,x2,…,xn ,表示从位置 1 到位置 N 的珠子的颜色,1≤xi≤c 。
第三行包含一个整数 Q ,表示命令数目。接下来的 Q 行每行一条命令,如上文所述。N≤500000 ,Q≤500000,c≤1000
**Output
对于每一个 C 和 CS 命令,应输出一个整数代表相应的答案。
Sample Input
5 3
1 2 3 2 1
4
C
R 2
P 5 5 2
CS 4 1
Sample Output
4
1
HINT
注意旋转命令旋转“珠子”但不改变“位置”的编号,而反转命令始终以位置 1 为对称轴。例如当 N=10 时,项链上的位置编号如图1:
但注意此时项链上的位置编号仍然如图1所示,于是翻转的对称轴不变。因而再执行一次“F”命令时,项链的颜色如图4所示。
2. 关于CountSegment命令CS命令表示查询一个“线段”中有多少个“部分”。尤其注意当查询的长度等于 N 时,我们仍然将查询部分作为“线段”理解。例如在图4所示的情况中,执行“CS 1 10”命令,查询从位置 1 开始到位置 10 结束的这个长度为 10 的线段中有多少个“部分”,于是得到返回值 3 。与之形成对照的是,若执行“C”命令,返回值则为 2
Solution
显而易见的线段树或者Splay,Splay比较好打就打Splay了…
操作一就是截下Splay的后k个元素插到开头,操作二就是给区间2~N翻转,区间颜色段数就维护一下左右端点的颜色就可以合并了。注意特判整个区间颜色相同的情况。
#include<cstdio>
#include<algorithm>
using namespace std;
template<typename T>inline void read(T &x){
T f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(x=0;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
x*=f;
}
const int maxn=500010;
struct Node{
int ch[2],fa,col,cl,cr;
int num,size,same;
bool rev;
Node(){ch[0]=ch[1]=fa=col=cl=cr=num=size=rev=same=0;}
}T[maxn];
int root,tot;
void update(int x){
if(T[x].ch[0]&&T[x].ch[1]){
T[x].cl=T[T[x].ch[0]].cl;
T[x].cr=T[T[x].ch[1]].cr;
T[x].num=T[T[x].ch[0]].num+T[T[x].ch[1]].num+1;
T[x].size=T[T[x].ch[0]].size+T[T[x].ch[1]].size+1;
if(T[T[x].ch[0]].cr==T[x].col)T[x].num--;
if(T[T[x].ch[1]].cl==T[x].col)T[x].num--;
}
else if(T[x].ch[0]){
T[x].cl=T[T[x].ch[0]].cl;
T[x].cr=T[x].col;
T[x].num=T[T[x].ch[0]].num+(T[T[x].ch[0]].cr!=T[x].col);
T[x].size=T[T[x].ch[0]].size+1;
}
else if(T[x].ch[1]){
T[x].cl=T[x].col;
T[x].cr=T[T[x].ch[1]].cr;
T[x].num=T[T[x].ch[1]].num+(T[T[x].ch[1]].cl!=T[x].col);
T[x].size=T[T[x].ch[1]].size+1;
}
else{
T[x].cl=T[x].cr=T[x].col;
T[x].num=T[x].size=1;
}
}
int Build(int *a,int l,int r,int fa=0){
if(l>r)return 0;
int x=++tot,mid=(l+r)>>1;
T[x].col=a[mid];T[x].fa=fa;
if(l==r){
T[x].cl=T[x].cr=a[mid];
T[x].num=T[x].size=1;
return x;
}
T[x].ch[0]=Build(a,l,mid-1,x);
T[x].ch[1]=Build(a,mid+1,r,x);
return update(x),x;
}
void pushsame(int x,int c){
T[x].col=T[x].cl=T[x].cr=T[x].same=c;
T[x].num=1;T[x].rev=false;
}
void pushrev(int x){
T[x].rev^=1;
swap(T[x].cl,T[x].cr);
swap(T[x].ch[0],T[x].ch[1]);
}
void pushdown(int x){
if(T[x].same){
pushsame(T[x].ch[0],T[x].same);
pushsame(T[x].ch[1],T[x].same);
T[x].same=0;
}
if(T[x].rev){
pushrev(T[x].ch[0]);
pushrev(T[x].ch[1]);
T[x].rev=false;
}
}
int getson(int x){
return x==T[T[x].fa].ch[1];
}
void rotate(int x){
int fa=T[x].fa,fafa=T[fa].fa,k=getson(x);
pushdown(fa);pushdown(x);
T[fa].ch[k]=T[x].ch[k^1];
if(T[x].ch[k^1])T[T[x].ch[k^1]].fa=fa;
T[T[T[x].ch[k^1]=fa].fa=x].fa=fafa;
if(fafa)T[fafa].ch[fa==T[fafa].ch[1]]=x;
update(fa);update(x);
}
void Splay(int x,int f=0){
for(int fa;(fa=T[x].fa)!=f;rotate(x))
if(T[fa].fa!=f)rotate(getson(x)==getson(fa)?fa:x);
if(!f)root=x;
}
int Find(int rnk){
int x=root;
while(1){
pushdown(x);
if(T[x].ch[0]&&T[T[x].ch[0]].size>=rnk)x=T[x].ch[0];
else{
int temp=(T[x].ch[0]?T[T[x].ch[0]].size:0)+1;
if(temp==rnk)return x;
rnk-=temp;x=T[x].ch[1];
}
}
}
int n,m,c,a[maxn];
int main(){
read(n);read(c);
for(int i=1;i<=n;i++)read(a[i]);
root=Build(a,1,n);
read(m);
while(m--){
char opt[4];
int l,r,k;
scanf("%s",opt);
if(opt[0]=='R'){
read(k);
Splay(Find(n-k));
int temp=T[root].ch[1],fir=Find(1);
T[root].ch[1]=0;update(root);
T[T[temp].fa=fir].ch[0]=temp;
update(fir);Splay(temp);
}
else if(opt[0]=='F'){
Splay(Find(1));
pushrev(T[root].ch[1]);
update(root);
}
else if(opt[0]=='S'){
read(l);read(r);
int x=Find(l),y=Find(r);
if(T[x].col==T[y].col)continue;
int cx=T[x].col,cy=T[y].col;
T[x].col=cy;update(x);Splay(x);
T[y].col=cx;update(y);Splay(y);
}
else if(opt[0]=='P'){
read(l);read(r);read(k);
if(l<=r){
if(l==1&&r==n)pushsame(root,k);
else if(l==1)Splay(Find(r+1)),pushsame(T[root].ch[0],k),update(root);
else if(r==n)Splay(Find(l-1)),pushsame(T[root].ch[1],k),update(root);
else{
Splay(Find(l-1));Splay(Find(r+1),root);
pushsame(T[T[root].ch[1]].ch[0],k);
update(T[root].ch[1]);update(root);
}
}
else{
Splay(Find(l-1));pushsame(T[root].ch[1],k);update(root);
Splay(Find(r+1));pushsame(T[root].ch[0],k);update(root);
}
}
else if(opt[0]=='C'&&opt[1]=='\0'){
int temp=T[root].num-(T[root].cl==T[root].cr);
printf("%d\n",max(temp,1));
}
else if(opt[0]=='C'&&opt[1]=='S'){
read(l);read(r);
int temp=0;
if(l<=r){
if(l==1&&r==n)temp=T[root].num;
else if(l==1)Splay(Find(r+1)),temp=T[T[root].ch[0]].num;
else if(r==n)Splay(Find(l-1)),temp=T[T[root].ch[1]].num;
else{
Splay(Find(l-1));Splay(Find(r+1),root);
temp=T[T[T[root].ch[1]].ch[0]].num;
}
}
else{
Splay(Find(l-1));temp+=T[T[root].ch[1]].num;
Splay(Find(r+1));temp+=T[T[root].ch[0]].num;
temp-=(T[root].cl==T[root].cr);
}
printf("%d\n",temp);
}
}
return 0;
}