zoukankan      html  css  js  c++  java
  • 洛谷P3165 [CQOI2014]排序机械臂 平衡树Splay

    P3165 [CQOI2014]排序机械臂

    题目链接

    题意

    给一个长度为(n)序列(a_1,a_2,dots,a_n),第(i)次操作选择第(i)小的数字,找到它的位置(p),翻转区间([i,p])

    分析

    先不考虑哨兵(-inf)(inf)

    在平衡树中插入下标(1sim n),对每个数字(a_i)记录它的下标在平衡树中的结点编号(j)(事实上(j=i)),然后对(pair(a_i,j))排序,从左到右每次将结点(j)旋转到根节点,它的左子树的大小+1即为它在数组中的位置,然后像文艺平衡树那样再区间翻转一下就好了。

    Code

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<iomanip>
    #include<sstream>
    #include<cstdio>
    #include<string>
    #include<vector>
    #include<bitset>
    #include<queue>
    #include<cmath>
    #include<stack>
    #include<set>
    #include<map>
    #define rep(i,x,n) for(int i=x;i<=n;i++)
    #define per(i,n,x) for(int i=n;i>=x;i--)
    #define sz(a) int(a.size())
    #define rson mid+1,r,p<<1|1
    #define pii pair<int,int>
    #define lson l,mid,p<<1
    #define ll long long
    #define pb push_back
    #define mp make_pair
    #define se second
    #define fi first
    using namespace std;
    const double eps=1e-8;
    const int mod=1e9+7;
    const int N=1e5+10;
    const int inf=1e9;
    int n,m;
    int rt,tot,ch[N][2],sz[N],val[N],fa[N],cnt[N];
    int tag[N];
    struct Splay{
        void maintain(int x){
            sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+cnt[x];
        }
        bool get(int x){
            return x==ch[fa[x]][1];
        }
        void clear(int x){
            ch[x][0]=ch[x][1]=fa[x]=val[x]=sz[x]=cnt[x]=0;
        }
        void pd(int x){
            if(x&&tag[x]){
                tag[ch[x][0]]^=1;
                tag[ch[x][1]]^=1;
                swap(ch[x][0],ch[x][1]);
                tag[x]=0;
            }
        }
        void rotate(int x){
            int y=fa[x],z=fa[y],chk=get(x);
            pd(x),pd(y);
            ch[y][chk]=ch[x][chk^1];
            fa[ch[x][chk^1]]=y;
            ch[x][chk^1]=y;
            fa[y]=x;
            fa[x]=z;
            if(z) ch[z][ y==ch[z][1] ]=x;
            maintain(y);
            maintain(x);
        }
        void splay(int x,int goal=0){
            for(int f;(f=fa[x])!=goal;rotate(x)){
                pd(fa[f]);pd(f);pd(x);
                if(fa[f]!=goal) rotate(get(x)==get(f)?f:x);
            }
            if(goal==0) rt=x;
        }
        void ins(int k){
            if(!rt){
                val[++tot]=k;
                cnt[tot]++;
                rt=tot;
                maintain(rt);
                return;
            }
            int cnr=rt,f=0;
            while(1){
                if(val[cnr]==k){
                    cnt[cnr]++;
                    maintain(cnr);
                    maintain(f);
                    splay(cnr);
                    break;
                }
                f=cnr;
                cnr=ch[cnr][val[cnr]<k];
                if(!cnr){
                    val[++tot]=k;
                    cnt[tot]++;
                    fa[tot]=f;
                    ch[f][val[f]<k]=tot;
                    maintain(tot);
                    maintain(f);
                    splay(tot);
                    break;
                }
            }
        }
        int kth(int k){
            int cnr=rt;
            while(1){
                pd(cnr);
                if(ch[cnr][0]&&sz[ch[cnr][0]]>=k){
                    cnr=ch[cnr][0];
                }else{
                    k-=cnt[cnr]+sz[ch[cnr][0]];
                    if(k<=0){
                        return cnr;
                    }
                    cnr=ch[cnr][1];
                }
            }
        }
        void reverse(int x,int y){
            int l=kth(x-1),r=kth(y+1);
            splay(l,0);
            splay(r,l);
            int pos=ch[rt][1];
            pos=ch[pos][0];
            tag[pos]^=1;
        }
    }S;
    pii a[N];
    int main(){
        //ios::sync_with_stdio(false);
        //freopen("in","r",stdin);
        scanf("%d",&n);
        S.ins(-inf);
        rep(i,1,n){
            scanf("%d",&a[i].fi);
            S.ins(i);
            a[i].se=i+1;
        }
        S.ins(inf);
        sort(a+1,a+n+1);
        rep(i,1,n){
            S.splay(a[i].se);
            int ans=sz[ch[rt][0]];
            S.reverse(i+1,ans+1);
            printf("%d ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    CSP2021&NOIP2021游记
    P3835[模板]可持久化平衡树【无旋Treap】
    P4688[Ynoi2016]掉进兔子洞【莫队,bitset】
    C# (CSharp) ADODB.Command示例
    求最大公约数 算法记录
    流逝时间+Windows下监测文件夹
    C# WinForm开发系列 文章索引
    09年搞笑签名
    高三班主任写给学生的一封信(在读大学的要看完)
    北京生存法则
  • 原文地址:https://www.cnblogs.com/xyq0220/p/13513139.html
Copyright © 2011-2022 走看看