zoukankan      html  css  js  c++  java
  • HYSBZ 3506 排序机械臂

    题意:
    给定一个长度为N的物品排列和一个可以把一段连续的物品翻转的机械臂,你要通过N次机械臂操作将物品按升序排序,第i次操作必须将第i个物品放在第i个位置上。即在第i次操作中,你需要用机械臂将区间[i,P[i]]翻转(P[i]为该次操作前第i个数的位置)。你在每次操作前需要输出P[i]。
    简化版:你需要维护一个序列,支持区间翻转与查询区间最小。
    题解:
    ①由于区间最小实际上每一次就是对应的整个数列的第k小,因此可以直接预处理解决,接下来考虑如何找到这个点,可以直接用一个指针解决,然后就是简单的无旋treap操作:
    ②给定一个平衡树上节点,求它在当前序列中的下标,首先我们先将这个点到平衡树根节点的标记下传,使用递归解决,然后就直接根据BST的性质查找即可。
    ③其余的就是按照题意进行区间rotate,这是无旋Treap的简单操作之一,不多赘述。

    #pragma GCC optimize (4)
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int maxn=100000+10;
    const int Inf=1e9;
    typedef long long LL;
    int n,A[maxn],num,root;
    struct Hash{
            int id,x;
            bool operator<(const Hash &A)const{
                    if(A.x==x)return id<A.id;
                    return x<A.x;
            }
    }Map[maxn];
    struct Treap{
            int lch,rch;
            int data,Min,size;
            bool lazy;
            #define L(u) a[u].lch
            #define R(u) a[u].rch
    }a[maxn<<1];
    typedef pair<int,int> D;
    void Init();
    void Pushup(int);
    void Rotate(int);
    void Pushdown(int);
    int Build(int,int);
    D Split(int,int);
    int Merge(int,int);
    int GetRank(int);
    int main(){
            a[0].Min=Inf;
            Init();
            return 0;
    }
    void Init(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&A[i]),Map[i].x=A[i],Map[i].id=i;
        sort(Map+1,Map+1+n);
        for(int i=1;i<=n;i++)
            A[Map[i].id]=i;
        root=Build(1,n);
        for(int i=1;i<=n;i++){
            int tmp=GetRank(i);
            printf("%d ",tmp+i-1);
            D y=Split(root,tmp);
            Rotate(y.first);
            root=Merge(y.first,y.second);
            root=Split(root,1).second;
        }
    }
    void Pushup(int u){
            a[u].Min=min(a[L(u)].Min,a[R(u)].Min);
            a[u].Min=min(a[u].Min,a[u].data);
            a[u].size=a[L(u)].size+a[R(u)].size+1;
    }
    void Rotate(int u){
            a[u].lazy^=1;
            swap(L(u),R(u));
    }
    void Pushdown(int u){
            a[u].lazy=0;
            if(L(u))Rotate(L(u));
            if(R(u))Rotate(R(u));
    }
    int Build(int left,int right){
            if(left>right)return 0;
            int mid=(left+right)>>1;
            int u=++num;
            a[u].lazy=0;
            a[u].data=A[mid];
            a[u].Min=Inf;
            L(u)=Build(left,mid-1);
            R(u)=Build(mid+1,right);
            Pushup(u);
            return u;
    }
    D Split(int u,int k){
            if(u==0)return D(0,0);
            if(a[u].lazy)Pushdown(u);
            D y;
            int num=a[L(u)].size;
            if(num>=k){
                    y=Split(L(u),k);
                    L(u)=y.second;
                    Pushup(u);
                    y.second=u;
            }else{
                    y=Split(R(u),k-num-1);
                    R(u)=y.first;
                    Pushup(u);
                    y.first=u;
            }
            return y;
    }
    int Merge(int A,int B){
            if(A==0)return B;
            if(B==0)return A;
            if(a[A].lazy)Pushdown(A);
            if(a[B].lazy)Pushdown(B);
            if(rand()%(a[A].size+a[B].size)<a[A].size){
                    a[A].rch=Merge(a[A].rch,B);
                    Pushup(A);
                    return A;
            }
            else{
                    a[B].lch=Merge(A,a[B].lch);
                    Pushup(B);
                    return B;
            }
    }
    int GetRank(int x){
            int u=root;
            int sum=0;
            while(1){
                    if(a[u].data==x)return sum+a[L(u)].size+1;
                    if(a[u].lazy)Pushdown(u);
                    if(a[L(u)].Min==x)u=L(u);
                    else sum+=a[L(u)].size+1,u=R(u);
            }
    }

  • 相关阅读:
    java学习
    瓜娃《guava》api快速入门
    List,set,Map 的用法和区别
    css selector
    字节流与字符流区别
    jsoup的elements类
    javaio-printwriter
    map遍历的四种方法
    kafka集群和zookeeper集群的部署,kafka的java代码示例
    Ubuntu12.04安装中文字体(转)
  • 原文地址:https://www.cnblogs.com/holy-unicorn/p/9510138.html
Copyright © 2011-2022 走看看