T公司是一家專門生產彩色珠子項鍊的公司,其生產的項鍊設計新穎、款式多樣、價格適中,廣受青年人的喜好。
最近T公司打算推出一款項鍊自助生產系統,使用該系統顧客能夠自行設計心目中的美麗項鍊。該項鍊自助生產系統包括硬件系統與軟件系統,軟件系統與用戶進行交互並控制硬件系統,硬件系統接受軟件系統的命令生產指定的項鍊。該系統的硬件系統已經完成,而軟件系統還沒有開發,T公司的人找到了正在參加全國信息學競賽的你,你能幫助T公司編寫一個軟件模擬系統嗎?一條項鍊包含 N 個珠子,每一個珠子的顏色是 1,2,…,c 中的一種。項鍊被固定在一個平板上,平板的某個位置被標記位置 1 ,按順時針方向其餘位置被記爲1,2,3,…,N。
你將要編寫的軟件系統應支持以下命令:
輸入文件第一行包含兩個整數 N,c ,分別表示項鍊包含的珠子數目以及顏色數目。
第二行包含 N 個整數,x1,x2,…,xn ,表示從位置 1 到位置 N 的珠子的顏色,1≤xi≤c 。
第三行包含一個整數 Q ,表示命令數目。接下來的 Q 行每行一條命令,如上文所述。N≤500000 ,Q≤500000,c≤1000
對於每個 C 和 CS 命令,應輸出一個整數表明相應的答案。php
注意旋轉命令旋轉「珠子」但不改變「位置」的編號,而反轉命令始終以位置 1 爲對稱軸。例如當 N=10 時,項
鏈上的位置編號如圖1:
但注意此時項鍊上的位置編號仍然如圖1所示,因而翻轉的對稱軸不變。於是再執行一次「F」命令時,項鍊的顏色如圖4所示。
2. 關於CountSegment命令CS命令表示查詢一個「線段」中有多少個「部分」。尤爲注意當查詢的長度等於 N 時,咱們仍然將查詢部分做爲「線段」理解。例如在圖4所示的狀況中,執行「CS 1 10」命令,查詢從位置 1 開始到位置 10 結束的這個長度爲 10 的線段中有多少個「部分」,因而獲得返回值 3 。與之造成對照的是,若執行「C」命令,返回值則爲 2
Splay的常數好像有點大,調試的時候忽然想到能夠利用線段樹來作..代碼量和常數應該會小很多....設計
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
inline int read()
{
int x=0,f=1; char ch=getchar();
while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
#define MAXN 500010
int N,C,Q,a[MAXN];
namespace SplayTree{
#define lson(x) son[x][0]
#define rson(x) son[x][1]
int size[MAXN],fa[MAXN],son[MAXN][2],sz,root;
int val[MAXN],lc[MAXN],rc[MAXN],cnt[MAXN],rev[MAXN],cov[MAXN];
inline void Newnode(int &x,int last,int v)
{
x=++sz;
fa[x]=last; son[x][0]=son[x][1]=0;
val[x]=lc[x]=rc[x]=v;
cnt[x]=v? 1:0;
}
inline void Update(int x)
{
if (!x) return;
size[x]=size[lson(x)]+size[rson(x)]+1;
cnt[x]=cnt[lson(x)]+cnt[rson(x)]+1;
lc[x]=rc[x]=val[x];
if (lson(x)) lc[x]=lc[lson(x)],cnt[x]-=(val[x]==rc[lson(x)]? 1:0);
if (rson(x)) rc[x]=rc[rson(x)],cnt[x]-=(val[x]==lc[rson(x)]? 1:0);
}
inline int Build(int l,int r,int last)
{
int mid=(l+r)>>1,x;
Newnode(x,last,a[mid]);
if (mid-1>=l) son[x][0]=Build(l,mid-1,x);
if (mid+1<=r) son[x][1]=Build(mid+1,r,x);
Update(x);
return x;
}
inline void Rev(int x) {if (!x) return; rev[x]^=1; swap(son[x][1],son[x][0]); swap(lc[x],rc[x]);}
inline void Cov(int x,int c) {if (!x) return; cov[x]=c; rev[x]=0; cnt[x]=1; lc[x]=rc[x]=val[x]=c;}
inline void Pushdown(int x)
{
if (cov[x])
Cov(son[x][0],cov[x]),Cov(son[x][1],cov[x]),cov[x]=0;
if (rev[x])
Rev(son[x][0]),Rev(son[x][1]),rev[x]^=1;
}
inline int Right(int x) {return son[fa[x]][1]==x;}
inline void Rotate(int x)
{
int y=fa[x],z=fa[y],w=Right(x);
Pushdown(y); Pushdown(x);
son[y][w]=son[x][w^1]; fa[son[y][w]]=y;
fa[y]=x; son[x][w^1]=y; fa[x]=z;
if (z) son[z][son[z][1]==y]=x;
Update(y); Update(x);
}
inline void Splay(int x,int tar)
{
for (int y; (y=fa[x])!=tar; Rotate(x))
if (fa[y]!=tar) Rotate(Right(x)==Right(y) ? y:x);
if (!tar) root=x;
}
inline int Find(int x,int k)
{
Pushdown(x);
if (size[son[x][0]]>=k) return Find(son[x][0],k);
if (size[son[x][0]]+1==k) return x;
return Find(son[x][1],k-size[son[x][0]]-1);
}
inline int Split(int l,int r)
{
int x=Find(root,l),y=Find(root,r+2);
Splay(x,0); Splay(y,root); return lson(rson(root));
}
inline void Move(int k)
{
if (!k || k==N) return;
int x=Split(N-k+1,N),y=fa[x];
fa[x]=0; son[y][0]=0;
Update(y); Update(fa[y]);
int xx=Find(root,1),yy=Find(root,2);
Splay(xx,0); Splay(yy,root);
son[rson(root)][0]=x; fa[x]=rson(root);
Update(rson(root)); Update(root);
}
inline void Cover(int l,int r,int c)
{
int x;
if (l<=r)
x=Split(l,r),Cov(x,c);
else
Move(N-l+1),Cover(1,r+N-l+1,c),Move(l-1);
}
inline int Query(int l,int r)
{
int x;
if (l<=r)
return cnt[Split(l,r)];
else
return Move(N-l+1),x=Query(1,r+N-l+1),Move(l-1),x;
}
inline int Query()
{
int x=cnt[Split(1,N)],lc=val[Find(root,2)],rc=val[Find(root,N+1)];
return rc==lc? max(x-1,1):x;
}
inline void Swap(int x,int y)
{
int xc=val[Find(root,x+1)],yc=val[Find(root,y+1)];
Cover(x,x,yc); Cover(y,y,xc);
}
inline void Rever() {int x=Split(2,N); Rev(x);}
}using namespace SplayTree;
int main()
{
N=read(),C=read();
for (int i=1; i<=N; i++) a[i]=read();
Newnode(root,0,0);
Newnode(son[root][1],root,0);
son[son[root][1]][0]=SplayTree::Build(1,N,son[root][1]);
Q=read();
while (Q--) {
char opt[3]; scanf("%s",opt+1);
int x,y,c,k;
switch (opt[1]) {
case 'R' : k=read(); SplayTree::Move(k); break;
case 'F' : SplayTree::Rever(); break;
case 'S' : x=read(),y=read(); SplayTree::Swap(x,y); break;
case 'P' : x=read(),y=read(),c=read(); SplayTree::Cover(x,y,c); break;
case 'C' : if (opt[2]=='S') x=read(),y=read(),printf("%d\n",SplayTree::Query(x,y)); else printf("%d\n",SplayTree::Query()); break;
}
}
return 0;
}