[題解]bzoj1493 NOI2007項鍊工廠

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;
}
發佈了81 篇原創文章 · 獲贊 43 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章