poj 3580 splay

题意:
1 区间每个数加D
2 区间翻转
3 区间向右滚动T次 12345滚动1次为51234
4 第x个数后面添加p
5 删除第x个数
6 询问区间最小值

分析:结点[0]的信息不能修改,原因不明。。。

翻转操作不能直接rev[x]=1, 而要rev[x]^=1。 keyTree未必已经pushDown

pushDown(x) if(x==0)return; 可以节省不少时间

 

 

#define keyTree (ch[ ch[root][1] ][0])
const int vaf=0x7fffffff;
const int MaxN = 100005;
struct SplayTree{
    int sz[MaxN];
    int ch[MaxN][2];//ch[][0]左孩子  ch[][1]右孩子
    int pre[MaxN];//父结点
    int root,top1,top2;
    int sta[MaxN],que[MaxN];

    inline void Rotate(int x,int f) {//f==0左旋转  f==1右旋转
        int y=pre[x];
        PushDown(y); PushDown(x);
        ch[y][!f]=ch[x][f]; pre[ch[x][f]]=y;
        pre[x]=pre[y];
        if(pre[x]) ch[pre[y]][ch[pre[y]][1]==y]=x;
        ch[x][f]=y; pre[y]=x;
        PushUp(y);
        //if(y==root)root=x;
    }
    inline void Splay(int x,int goal) {//将x旋转到goal的下面
        PushDown(x);
        while(pre[x]!=goal) {
            if(pre[pre[x]]==goal) Rotate(x,ch[pre[x]][0]==x);
            else{
                int y=pre[x],z=pre[y],f=(ch[z][0]==y);
                if(ch[y][f]==x) Rotate(x,!f),Rotate(x,f);
                else Rotate(y,f),Rotate(x,f);
            }
        }
        PushUp(x);
        if(goal==0) root=x;
    }
    inline void RotateTo(int k,int goal) {//将第k个数旋转到goal下面
        int x=root;                                                 //cout<<k<<endl;
        PushDown(x);
        k++; //由于加入了两个边界结点  所以应为k+1位
        while(sz[ch[x][0]]!=k-1) {
            if(k-1<sz[ch[x][0]]) x=ch[x][0];
            else k-=(sz[ch[x][0]]+1), x=ch[x][1];
            PushDown(x);
        }                                                       //if(k==1)cout<<x<<endl;
        Splay(x,goal);
    }
    inline void Delete(int x) {//把以x为祖先结点删掉放进内存池,回收内存
        int fa=pre[x],head=0,tail=0;
        for(que[tail++]=x;head<tail;head++){
            sta[top2++]=que[head];
            if(ch[que[head]][0]) que[tail++]=ch[que[head]][0];
            if(ch[que[head]][1]) que[tail++]=ch[que[head]][1];
        }
        ch[fa][ch[fa][1]==x]=0;
        while(fa!=root) PushUp(fa),fa=pre[fa];
        PushUp(root);
    }
    inline int pred(int x){//在x的子树中找x的前驱
        PushDown(x);
        int y=ch[x][0];
        PushDown(y);
        while(ch[y][1]) y=ch[y][1],PushDown(y);
        return y;
    }
    inline int succ(int x){//在x的子树中找x的后继
        PushDown(x);
        int y=ch[x][1];
        PushDown(y);
        while(ch[y][0]) y=ch[y][0],PushDown(y);
        return y;
    }
    void shuchu(int x){
        //cout<<"结点 "<<x<<"   左结点 "<<ch[x][0]<<"   右结点 "<<ch[x][1]<<"   值 "<<val[x]<<endl;
        if(ch[x][0])shuchu(ch[x][0]);
        if(ch[x][1])shuchu(ch[x][1]);
    }
    //以上一般不修改//////////////////////////////////////////////////

    inline void NewNode(int &x,int c) {     //需再处理pre[x]
        if(top2) x=sta[--top2];//用栈手动压的内存池
        else x=++top1;
        ch[x][0]=ch[x][1]=0;
        sz[x]=1;

        val[x]=Min[x]=c;    //
        add[x]=rev[x]=0;   //
    }
    inline void makeTree(int &x,int l,int r,int arr[],int father){
        if(l>r) return;
        int m=(l+r)>>1;
        NewNode(x,arr[m]);    //num[m]权值改成题目所需的
        makeTree(ch[x][0],l,m-1,arr,x);
        makeTree(ch[x][1],m+1,r,arr,x);
        pre[x]=father;
        PushUp(x);
    }
    inline void init(int n) {
        ch[0][0]=ch[0][1]=pre[0]=sz[0]=0;
        root=top1=top2=0;
        add[0]=rev[0]=0;    //
        val[0]=Min[0]=vaf;

        //为了方便处理边界,加两个边界顶点
        NewNode(root,vaf);   //
        NewNode(ch[root][1],vaf);    //
        pre[top1]=root;
        sz[root]=2;

        makeTree(keyTree,1,n,num,ch[root][1]);
        PushUp(ch[root][1]); PushUp(root);
    }


    inline void PushDown(int x) {
        if(x==0) return;
        int l=ch[x][0],r=ch[x][1];
        if(rev[x]){
            rev[x]^=1;
            if(l) rev[ch[x][0]]^=1;
            if(r) rev[ch[x][1]]^=1;
            swap(ch[x][0],ch[x][1]);
            //int t=l; ch[x][0]=r; ch[x][1]=t;
        }
        if(add[x]){
            if(l) add[l]+=add[x],val[l]+=add[x],Min[l]+=add[x];
            if(r) add[r]+=add[x],val[r]+=add[x],Min[r]+=add[x];
            add[x]=0;
        }
    }

    inline void PushUp(int x) {
        sz[x]=1+sz[ch[x][0]]+sz[ch[x][1]];//sz[0]==0
        int l=ch[x][0],r=ch[x][1];
        //Min[x]=Min[l]<Min[r]?Min[l]:Min[r];
        //Min[x]=Min[x]<val[x]?Min[x]:val[x];
        Min[x]=min(Min[l],Min[r]);
        Min[x]=min(Min[x],val[x]);
    }

    inline void Add(int a,int b,int d){
        RotateTo(a-1,0);    RotateTo(b+1,root);
                                            //cout<<val[root]<<' '<<val[ch[root][1]]<<' '<<Min[root]<<' '<<Min[ch[root][1]]<<endl;
        add[keyTree]+=d; val[keyTree]+=d; Min[keyTree]+=d;
        PushUp(ch[root][1]); PushUp(root);
    }

    inline void reverse(int a,int b){
        RotateTo(a-1,0); RotateTo(b+1,root);
        rev[keyTree]^=1;                                                //翻转不能直接 =1
    }

    inline void revolve(int a,int b,int d){             //shuchu(root);cout<<endl;
        //d=(d%(b-a+1)+2*(b-a+1))%(b-a+1);
        d=d%(b-a+1);
        RotateTo(b-d,0);    RotateTo(b+1,root);                             //shuchu(root);cout<<endl;
        PushDown(keyTree);
        int key=keyTree;    keyTree=0;
        PushUp(ch[root][1]);    PushUp(root);
        RotateTo(a-1,0);    RotateTo(a,root);
        keyTree=key;
        if(key) pre[key]=ch[root][1];
        PushUp(ch[root][1]); PushUp(root);
    }

    inline void insert(int a,int b){
        RotateTo(a,0);    RotateTo(a+1,root);
        NewNode(keyTree,b);
        pre[keyTree]=ch[root][1];
        PushUp(ch[root][1]); PushUp(root);
    }

    inline void delet(int a){
        RotateTo(a-1,0);    RotateTo(a+1,root);
        Delete(keyTree);
    }

    inline void query(int a,int b){
        RotateTo(a-1,0);    RotateTo(b+1,root);
        printf("%d\n",Min[keyTree]);
    }

    int num[MaxN];
    int val[MaxN];
    int add[MaxN];
    int Min[MaxN];
    int rev[MaxN];
}spt;


int main() {
    int n , m;
    int a,b,d;
    char c[10];
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&spt.num[i]);
    spt.init(n);
    scanf("%d",&m);
    for(int i=0;i<m;i++) {
        scanf("%c",&c[0]);
        while(c[0]<'A'||c[0]>'Z') scanf("%c",&c[0]);
        scanf("%s",c+1);
        if(c[0]=='A'){ scanf("%d%d%d",&a,&b,&d); spt.Add(a,b,d); }
        else if(c[0]=='R'&&c[3]=='E'){scanf("%d%d",&a,&b); spt.reverse(a,b); }
        else if(c[0]=='R'){ scanf("%d%d%d",&a,&b,&d); spt.revolve(a,b,d); }
        else if(c[0]=='I'){ scanf("%d%d",&a,&b); spt.insert(a,b); }
        else if(c[0]=='D'){ scanf("%d",&a); spt.delet(a); }
        else if(c[0]=='M'){ scanf("%d%d",&a,&b); spt.query(a,b); }
    }
    return 0;
}

 

posted @ 2013-06-22 16:25  心向往之  阅读(241)  评论(0编辑  收藏  举报