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

    1552: [Cerc2007]robotic sort

    Time Limit: 5 Sec  Memory Limit: 64 MB
    Submit: 1198  Solved: 457
    [Submit][Status][Discuss]

    Description

    Input

    输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000。
    第二行为N个用空格隔开的正整数,表示N个物品最初排列的编号。

    Output

    输出共一行,N个用空格隔开的正整数P1,P2,P3…Pn,Pi表示第i次操作前第i小的物品所在的位置。 
    注意:如果第i次操作前,第i小的物品己经在正确的位置Pi上,我们将区间[Pi,Pi]反转(单个物品)。

    Sample Input

    6
    3 4 5 1 6 2

    Sample Output

    4 6 4 5 6 6

    HINT

     

    Source

    splay区间反转
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define INF 0x7fffffff
    int n;
    const int maxn = 100020;
    struct Data{
        int a,pos;
        bool operator < (const Data & q)const {
            if(q.a==a)return pos<q.pos;
            else return a<q.a;    
        }
    }l[maxn];
    int mn[maxn],size[maxn],root,data[maxn],ch[maxn][2],mnpos[maxn];
    int rev[maxn],fa[maxn];
    inline void pushdown(int x)
    {
        rev[x]=0;
        rev[ch[x][0]]^=1;
        rev[ch[x][1]]^=1;
        swap(ch[ch[x][0]][0],ch[ch[x][0]][1]);
        swap(ch[ch[x][1]][0],ch[ch[x][1]][1]);
    }
    inline void pushup(int x)
    {
        mn[x]=min(data[x],min(mn[ch[x][1]],mn[ch[x][0]]));
        if(mn[x]==data[x])mnpos[x]=x;
        else if(mn[x]==mn[ch[x][0]])mnpos[x]=mnpos[ch[x][0]];
        else mnpos[x]=mnpos[ch[x][1]];
        size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
    }
    inline int getkth(int k,int rt)
    {
        if(rev[rt])pushdown(rt);
        if(k==size[ch[rt][0]]+1)return rt;
        if(k<size[ch[rt][0]]+1)return getkth(k,ch[rt][0]);
        else getkth(k-size[ch[rt][0]]-1,ch[rt][1]);
    }
    
    inline int son(int x){
        return ch[fa[x]][1]==x;
    }
    void rotate(int x)
    {
        int y=fa[x],z=fa[y],b=son(x),c=son(y),a=ch[x][!b];
        if(z)ch[z][c]=x;else root=x;fa[x]=z;
        if(a)fa[a]=y;ch[y][b]=a;
        ch[x][!b]=y;fa[y]=x;
        pushup(y),pushup(x);
    }
    void splay(int &x,int i) {
        while(fa[x]!=i)
        {
            int y=fa[x],z=fa[y];
            if(z==i){
                rotate(x);
            }else {
                if(rev[z])pushdown(z);if(rev[y])pushdown(y);if(rev[x])pushdown(x);
                if(son(x)==son(y)) {
                    rotate(y),rotate(x);
                }
                else {
                    rotate(x);rotate(x);
                }
            }
        }
    }
    int getmnpos(int l,int r)
    {
        int ll=getkth(l-1,root);
        int rr=getkth(r+1,root);
        splay(ll,0);
        splay(rr,ll);
        return mnpos[ch[rr][0]];
    }
    inline void reverse(int l,int r)
    {
        int ll=getkth(l-1,root),rr=getkth(r+1,root),p;
        splay(ll,0);splay(rr,ll);
        p=ch[rr][0];rev[p]^=1;
        swap(ch[p][0],ch[p][1]);
    }
    int main() {
        scanf("%d",&n);
        for(int i=2;i<=n+1;i++) scanf("%d",&l[i].a),l[i].pos=i;
        sort(l+2,l+n+2);
        for(int i=2;i<=n+1;i++)data[l[i].pos]=i;
        for(int i=0;i<=n+2;i++)mn[i]=INF;
        data[0]=data[1]=data[n+2]=INF;root=1;
        for(int i=1;i<=n+2;i++) {
            fa[i]=i-1;
            ch[i][1]=i+1;
        }
        ch[n+2][1]=0;
        for(int i=n+2;i>=1;i--) {
            pushup(i);
        }
        for(int i=1;i<=n;i++)
        {
            int po=getmnpos(i+1,n+1);
            splay(po,0);
            printf("%d",size[ch[po][0]]);
            reverse(i+1,size[ch[po][0]]+1);
            if(i!=n)printf(" ");
        }
        return 0;
    }
  • 相关阅读:
    卢卡斯定理算法模板
    求组合数的O(n^2)和O(n)解法及模板
    求逆元的方法及模板
    扩展欧基里德算法模板
    牛客练习赛43-F(简单容斥)
    容斥原理
    牛客网练习赛43-C(图论)
    折半搜索
    枚举+树状数组(经典)
    思维并查集/网络流和二分
  • 原文地址:https://www.cnblogs.com/sssy/p/7348823.html
Copyright © 2011-2022 走看看