zoukankan      html  css  js  c++  java
  • 1552: [Cerc2007]robotic sort

    这道题用splay写 先离散化数据保证按题目所述顺序来写 按原序作为键值建树 维护区间最小值去跑 每次将i的位置 和 n的位置x和y找出来后 将x旋转到root y旋转到x的有儿子 这时y的左子树就是所求区间 找出区间最小值和他的位置之后 旋转最小值到root 这时他左子树的大小+1就是他现处位置 然后将i到最小值位置中间的区间打上标记等待旋转 这样全部处理完就okay了
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int read(){
        int ans=0,f=1,c=getchar();
        while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();}
        return ans*f;
    }
    const int M=100505,inf=1000000000;
    int n,root,c[M][2],mn[M],pos[M],ans[M],rev[M],fa[M],size[M],v[M],top,s[M];
    struct node{int v,pos;}tr[M];
    bool cmp(node a,node b){return ((a.v<b.v)||(a.v==b.v&&a.pos<b.pos));}
    bool operator<(node a,node b){return a.pos<b.pos;}
    void push_up(int k){
        int l=c[k][0],r=c[k][1];
        size[k]=size[l]+size[r]+1;
        pos[k]=k; mn[k]=v[k];
        if(mn[l]<mn[k]){ mn[k]=mn[l]; pos[k]=pos[l];}
        if(mn[r]<mn[k]){ mn[k]=mn[r]; pos[k]=pos[r];}
    }
    void push_down(int k){
        int l=c[k][0],r=c[k][1];
        rev[k]=0; rev[l]^=1; rev[r]^=1;
        swap(c[k][0],c[k][1]);
    }
    int build(int l,int r){
        if(l>r) return 0;
        int m=(l+r)>>1; 
        size[m]=1; pos[m]=m; 
        c[m][0]=build(l,m-1);
        c[m][1]=build(m+1,r);
        for(int i=0;i<2;i++) if(c[m][i]) fa[c[m][i]]=m;
        push_up(m);
        return m;
    }
    int find(int x,int rank){
        if(rev[x]) push_down(x);
        int l=c[x][0],r=c[x][1];
        if(size[l]+1==rank) return x;
        else if(size[l]>=rank) return find(l,rank);
        else return find(r,rank-size[l]-1);
    }
    void rotate(int x,int &k){
        int y=fa[x],z=fa[y],l=0,r=1;
        if(c[y][1]==x) l=1,r=0;
        if(y==k) k=x;
        else{if(c[z][0]==y) c[z][0]=x; else c[z][1]=x;}
        fa[x]=z; fa[y]=x; fa[c[x][r]]=y;
        c[y][l]=c[x][r]; c[x][r]=y;
        push_up(x); push_up(y);
    }
    void splay(int x,int &k){
        top=0;s[++top]=x;
        for(int i=x;fa[i];i=fa[i])
            s[++top]=fa[i];
        for(int i=top;i;i--)
            if(rev[s[i]]) push_down(s[i]);
        while(x!=k){
            int y=fa[x],z=fa[y];
            if(y!=k){
                if(c[z][0]==y^c[y][0]==x) rotate(y,k);
                else rotate(x,k);
            }
            rotate(x,k);
        }
    }
    int push_ans(int l,int r){
        int x=find(root,l),y=find(root,r+2);
        splay(x,root); splay(y,c[x][1]);
        return pos[c[y][0]];
    }
    void rever(int l,int r){
        int x=find(root,l),y=find(root,r+2);
        splay(x,root); splay(y,c[x][1]);
        rev[c[y][0]]^=1;
    }
    int main()
    {
        n=read(); mn[0]=inf; 
        tr[1].v=tr[n+2].v=inf; 
        for(int i=2;i<=n+1;i++) tr[i].v=read(),tr[i].pos=i;
        sort(tr+2,tr+2+n,cmp);
        for(int i=2;i<=n+1;i++) tr[i].v=i-1;
        sort(tr+2,tr+2+n); for(int i=2;i<=n+1;i++) v[i]=tr[i].v;
        root=build(1,n+2); 
        for(int i=1;i<=n;i++){
            int x=push_ans(i,n);
            splay(x,root);
            ans[i]=size[c[x][0]];
            rever(i,ans[i]);
        }
        for(int i=1;i<=n;i++){ printf("%d",ans[i]); if(i!=n) printf(" ");}
        return 0;
    }
    View Code
  • 相关阅读:
    NOIP200801 ISBN号码
    NOIP200902分数线划定
    NOIP200901多项式输出
    NOIP200603 Jam的计数法
    HDNOIP201102读数
    Modular Inverse(扩展欧几里得)
    青蛙的约会(扩展欧几里得)
    A Famous City(单调栈)
    Triangles
    2971: 魔族密码 (trie树)
  • 原文地址:https://www.cnblogs.com/lyzuikeai/p/6916557.html
Copyright © 2011-2022 走看看