[BZOJ1493][NOI2007]项链工厂

来源:互联网 发布:web微信开发工具linux 编辑:程序博客网 时间:2024/05/18 04:59

原题地址

又是一道数据结构神题,卡了一晚上…

写一下其中几个写搓的地方:
1.update()时要clear()左右子树
2.查询完之后要记得把树merge()回去
3.交换操作那里,若i,j相等则直接退出,要不然会出错
4.染色\查询操作L<=R和L>R时split()的范围不同

UPDATE:split()函数里是不需要用到merge()的!这样就可以实现空间O(n lg n)的可持久化了.以后都要按新的写法来写.

AC code:

#include <cstdio>#include <cstdlib>#include <ctime>const int N=1000010;int n,c,q,tot;int a[N];struct nod{    int  c,lc,rc,sum,siz,tag,fix;    bool rev;    nod  *ch[2];    }*NIL,pool[N];struct Treap{    nod *root;    Treap(){        root=NIL=&pool[tot++];        for(int i=1;i<=n;i++) root=merge(root,newnod(a[i]));    }    nod* newnod(int c){        nod *p=&pool[tot++];        p->c=p->lc=p->rc=c;p->sum=p->siz=1;p->fix=rand()*rand()%N;        p->ch[0]=p->ch[1]=NIL;        return p;    }    void update(nod *p){        p->siz=p->ch[0]->siz+p->ch[1]->siz+1;p->lc=p->rc=p->c;p->sum=1;        clear(p->ch[0]);clear(p->ch[1]);        if(p->ch[0]!=NIL){            p->sum+=p->ch[0]->sum;            if(p->ch[0]->rc==p->c) p->sum--;            p->lc=p->ch[0]->lc;        }        if(p->ch[1]!=NIL){            p->sum+=p->ch[1]->sum;            if(p->ch[1]->lc==p->c) p->sum--;            p->rc=p->ch[1]->rc;        }    }    void clear(nod *p){        if(p==NIL) return ;        if(p->rev){            int tc=p->lc;p->lc=p->rc;p->rc=tc;            nod *tp=p->ch[0];p->ch[0]=p->ch[1];p->ch[1]=tp;            p->rev=0;p->ch[0]->rev^=1;p->ch[1]->rev^=1;        }        if(p->tag){            p->c=p->lc=p->rc=p->tag;p->sum=1;            p->ch[0]->tag=p->ch[1]->tag=p->tag;p->tag=0;        }    }    nod* merge(nod *p1,nod *p2){        clear(p1);clear(p2);        if(p1==NIL) return p2;        if(p2==NIL) return p1;        if(p1->fix<=p2->fix){            p2->ch[0]=merge(p1,p2->ch[0]);            update(p2);            return p2;        }        p1->ch[1]=merge(p1->ch[1],p2);        update(p1);        return p1;    }    void split(nod *p,nod *&p1,nod *&p2,int k){        clear(p);        if(p==NIL){            p1=p2=NIL;            return ;        }        if(p->ch[0]->siz+1<=k){            split(p->ch[1],p1,p2,k-p->ch[0]->siz-1);            p->ch[1]=p1;            update(p);            p1=p;        }        else{            split(p->ch[0],p1,p2,k);            p->ch[0]=p2;            update(p);            p2=p;        }    }    void work1(int k){        nod *p1,*p2;        split(root,p1,p2,n-k);        root=merge(p2,p1);    }    void work2(){        nod *p1,*p2;        split(root,p1,p2,1);        p2->rev^=1;        root=merge(p1,p2);    }    void work3(int L,int R){        if(L==R) return ;        if(L>R){int t=L;L=R;R=t;}        nod *p1,*p2,*p3,*p4,*p5,*p6,*p7,*p8;        split(root,p1,p6,L-1);        split(p6,p2,p7,1);        split(p7,p3,p8,R-L-1);        split(p8,p4,p5,1);        root=merge(p1,merge(p4,merge(p3,merge(p2,p5))));    }    void work4(int L,int R,int k){        nod *p1,*p2,*p3,*p4;        if(L<=R){            split(root,p1,p4,L-1);            split(p4,p2,p3,R-L+1);            p2->tag=k;        }        else{            int t=L;L=R;R=t;            split(root,p1,p4,L);            split(p4,p2,p3,R-L-1);            p1->tag=p3->tag=k;        }        root=merge(p1,merge(p2,p3));    }    int work5(){        clear(root);        if(root->sum==1) return 1;        int ans=work6(1,n);        if(root->lc==root->rc) ans--;        return ans;    }    int work6(int L,int R){        int ans;        nod *p1,*p2,*p3,*p4;        if(L<=R){            split(root,p1,p4,L-1);            split(p4,p2,p3,R-L+1);            clear(p2);            ans=p2->sum;        }        else{            int t=L;L=R;R=t;            split(root,p1,p4,L);            split(p4,p2,p3,R-L-1);            clear(p1);clear(p3);            ans=p1->sum+p3->sum;            if(p1->lc==p3->rc) ans--;        }        root=merge(p1,merge(p2,p3));        return ans;    }};int main(){    scanf("%d%d",&n,&c);    for(int i=1;i<=n;i++) scanf("%d",&a[i]);    Treap T;    scanf("%d",&q);    for(int i=1;i<=q;i++){        int L,R,x;        char s[1<<2];        scanf("%s",s);        if(s[0]=='R'){            scanf("%d",&x);            T.work1(x);        }        else if(s[0]=='F') T.work2();        else if(s[0]=='S'){            scanf("%d%d",&L,&R);            T.work3(L,R);        }        else if(s[0]=='P'){            scanf("%d%d%d",&L,&R,&x);            T.work4(L,R,x);        }        else if(s[0]=='C'&&s[1]=='\0') printf("%d\n",T.work5());        else{            scanf("%d%d",&L,&R);            printf("%d\n",T.work6(L,R));        }    }    return 0;}
0 0
原创粉丝点击