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;
}