• 【BZOJ】1552/3506 [Cerc2007]robotic sort


    【算法】splay

    【题解】

    splay维护序列,用权值(离散化)作为编号。每次找第i小的话直接找对应编号splay即可。

    但是这样splay没有下传翻转标记?直接暴力找到路径然后从根到改结点pushdown。暴力出奇迹!

    如果没有find就直接splay,一定记得更新设置splay为传值调用并且在过程中更新地址才能更新root。

    #include<cstdio>
    #include<cstring>
    #include<cctype>
    #include<algorithm>
    using namespace std;
    const int maxn=100010;
    int f[maxn],t[maxn][2],s[maxn],first[maxn],second[maxn],ord[maxn],a[maxn],node[maxn],n,root,ans[maxn];
    bool g[maxn];
    int read()
    {
        char c;int s=0;
        while(!isdigit(c=getchar()));
        do{s=s*10+c-'0';}while(isdigit(c=getchar()));
        return s;
    }
    bool cmp(int x,int y)
    {return (first[x]<first[y])||(first[x]==first[y]&&second[x]<second[y]);}
    void pushdown(int x)
    {
        if(g[x])
        {
            g[t[x][0]]^=1;g[t[x][1]]^=1;
            swap(t[x][0],t[x][1]);
            g[x]=0;
        }
    }
    void count(int x)
    {s[x]=s[t[x][0]]+1+s[t[x][1]];}
    void rotate(int x)
    {
        int k=x==t[f[x]][1];
        int y=f[x];
        t[y][k]=t[x][!k];f[t[x][!k]]=y;
        if(f[y])t[f[y]][y==t[f[y]][1]]=x;f[x]=f[y];f[y]=x;
        t[x][!k]=y;s[x]=s[y];//因为已经pushdown了所以不用传翻转标记
        count(y);
    }
    void splay(int &r,int x)
    {
        int tot=0;
        for(int i=x;i!=r;i=f[i])node[++tot]=i;node[++tot]=r;
        for(int i=tot;i>=1;i--)pushdown(node[i]);
        for(int fa=f[r];f[x]!=fa;)
        {
            if(f[f[x]]==fa){rotate(x);break;}//return之前要记得传参……所以还是break好…… 
            int X=x==t[f[x]][1],Y=f[x]==t[f[f[x]]][1];
            if(X^Y)rotate(x),rotate(x);
             else rotate(f[x]),rotate(x);
        }
        r=x;
    }
    void find(int &r,int k)
    {
        for(int x=r;x;)
        {
            pushdown(x);
            if(k<=s[t[x][0]]){x=t[x][0];continue;}
            if(k==s[t[x][0]]+1){splay(r,x);return;}
            k-=s[t[x][0]]+1;x=t[x][1];
        }
    }
    void build(int fa,int &x,int l,int r)
    {
        if(l>r)return;
        int mid=(l+r)>>1;
        x=a[mid];f[x]=fa;g[x]=0;s[x]=1;
        build(x,t[x][0],l,mid-1);
        build(x,t[x][1],mid+1,r);
        count(x);
    }
    //void writes()
    //{
    //    printf("------------------------------------------
    ");
    //    for(int i=0;i<=n+2;i++)printf("[%d]t1=%d t2=%d fa=%d g=%d s=%d
    ",i,t[i][0],t[i][1],f[i],g[i],s[i]);
    //    printf("------------------------------------------
    ");
    //}
    int main()
    {
        n=read();
        for(int i=1;i<=n;i++)
        {
            first[i]=read();
            second[i]=i;
            ord[i]=i;
        }
        sort(ord+1,ord+n+1,cmp);
        for(int i=1;i<=n;i++)a[ord[i]]=i;
        a[0]=n+1;a[n+1]=n+2;
        build(0,root,0,n+1);
        for(int i=1;i<=n;i++)
        {
            splay(root,i);
            int p=s[t[root][0]];
            ans[i]=p;
            find(root,i);
            find(t[root][1],p-i+2);
            g[t[t[root][1]][0]]^=1;
        }
        for(int i=1;i<n;i++)printf("%d ",ans[i]);
        printf("%d",ans[n]);
        return 0; 
    }
    View Code

    update:现在已改用fhq-treap代替splay。

  • 相关阅读:
    mysql架构篇之复制模式
    mysql架构篇之一主从从结构
    mysql架构篇之主从结构
    架构师的成长之路初片~Nginx篇~平滑升级
    架构师之成长之路~ceph~报错集
    架构师的成长之路初片~DNS
    python3.x~安装第三方模块
    架构师的成长之路初片~Ceph-object存储~及ceph常用命令
    架构师的成长之路初片~Ceph-block存储
    C# 多线程 Parallel.ForEach 和 ForEach 效率问题研究及理解
  • 原文地址:https://www.cnblogs.com/onioncyc/p/6916816.html
Copyright © 2020-2023  润新知