• BZOJ1552[Cerc2007]robotic sort&BZOJ3506[Cqoi2014]排序机械臂——非旋转treap


    题目描述

    输入

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

    输出

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

    样例输入

    6
    3 4 5 1 6 2

    样例输出

    4 6 4 5 6 6
     
    非旋转treap练习题。题目要求每次找到第i小的Pi并将i~Pi翻转,因为在第i次操作时,前i小的数在最前面不会被翻转,之后也不会被用到。那么我们可以对序列建非旋转treap每次找到最小的,然后删除掉它,再将它原位置之前的部分翻转即可。但发现不能只维护子树最小值,因为有相同值时要选编号小的,也不能有多个最小值优先遍历左子树,因为原先编号小的翻转后可能成了右子树。所以我们先将原序列排个序,按排序后的顺序作为他们新的权值,再按原顺序插入treap,这样每个点的权值就是独一无二的了,直接记录最小值每次查找即可。不要忘记查找时也要下传翻转标记。
    #include<set>
    #include<map>
    #include<stack>
    #include<queue>
    #include<cmath>
    #include<cstdio>
    #include<vector>
    #include<bitset>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define ll long long
    using namespace std;
    int n;
    int cnt;
    int root;
    int x,y,z;
    int v[100010];
    int s[100010];
    int r[100010];
    int mn[100010];
    int ls[100010];
    int rs[100010];
    int size[100010];
    struct miku
    {
        int val;
        int num;
        int rak;
    }a[100010];
    bool cmp1(miku a,miku b)
    {
        if(a.val!=b.val)
        {
            return a.val<b.val;
        }
        return a.num<b.num;
    }
    bool cmp2(miku a,miku b)
    {
        return a.num<b.num;
    }
    int build(int val)
    {
        int rt=++cnt;
        r[rt]=rand();
        v[rt]=val;
        mn[rt]=val;
        size[rt]=1;
        return rt;
    }
    void rotate(int rt)
    {
        swap(ls[rt],rs[rt]);
        s[rt]^=1;
    }
    void pushup(int rt)
    {
        size[rt]=size[ls[rt]]+size[rs[rt]]+1;
        mn[rt]=v[rt];
        if(ls[rt])
        {
            mn[rt]=min(mn[rt],mn[ls[rt]]);
        }
        if(rs[rt])
        {
            mn[rt]=min(mn[rt],mn[rs[rt]]);
        }
    }
    void pushdown(int rt)
    {
        if(s[rt])
        {
            if(ls[rt])
            {
                rotate(ls[rt]);
            }
            if(rs[rt])
            {
                rotate(rs[rt]);
            }
            s[rt]^=1;
        }
    }
    int merge(int x,int y)
    {
        if(!x||!y)
        {
            return x+y;
        }
        pushdown(x);
        pushdown(y);
        if(r[x]<r[y])
        {
            rs[x]=merge(rs[x],y);
            pushup(x);
            return x;
        }
        else
        {
            ls[y]=merge(x,ls[y]);
            pushup(y);
            return y;
        }
    }
    void split(int rt,int k,int &x,int &y)
    {
        if(!rt)
        {
            x=y=0;
            return ;
        }
        pushdown(rt);
        if(size[ls[rt]]<k)
        {
            x=rt;
            split(rs[rt],k-size[ls[rt]]-1,rs[x],y);
        }
        else
        {
            y=rt;
            split(ls[rt],k,x,ls[y]);
        }
        pushup(rt);
    }
    int rank(int rt)
    {
        pushdown(rt);
        int res=v[rt];
        if(ls[rt])
        {
            res=min(res,mn[ls[rt]]);
        }
        if(rs[rt])
        {
            res=min(res,mn[rs[rt]]);
        }
        if(res==mn[ls[rt]])
        {
            return rank(ls[rt]);
        }
        else if(res==v[rt])
        {
            return size[ls[rt]]+1;
        }
        else
        {
            return size[ls[rt]]+1+rank(rs[rt]);
        }
    }
    int main()
    {
        srand(20020419);
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i].val);
            a[i].num=i;
        }   
        sort(a+1,a+1+n,cmp1);
        for(int i=1;i<=n;i++)
        {
            a[i].rak=i;
        }
        sort(a+1,a+1+n,cmp2);
        for(int i=1;i<=n;i++)
        {
            root=merge(root,build(a[i].rak));
        }
        for(int i=1;i<=n;i++)
        {  
            int ans=rank(root);
            printf("%d",i-1+ans);
            if(i!=n)
            {
                printf(" ");
            }
            split(root,ans-1,x,y);
            split(y,1,y,z);
            rotate(x);
            root=merge(x,z);
        }
    }
  • 相关阅读:
    算法——排序方法总结(冒泡,快速,直接,希尔,堆,归并排序)
    C++函数调用之——值传递、指针传递、引用传递
    STM32(13)——SPI
    STM32(12)——CAN
    STM32(11)——DMA
    STM32(10)——窗口看门狗
    STM32(9)——通用定时器作为输入捕捉
    SRM32(8)——ADC和DAC
    WPF从入门到放弃系列第二章 XAML
    WPF从入门到放弃系列第一章 初识WPF
  • 原文地址:https://www.cnblogs.com/Khada-Jhin/p/9690398.html
Copyright © 2020-2023  润新知