zoukankan      html  css  js  c++  java
  • 【BZOJ3506】【Cqoi2014】排序机械臂

    传送门(因为BZOJ上没有题面...所以放的是luogu的)

    题意:你需要维护一个序列,支持区间翻转与查询区间最小。

    解题思路:由于区间最小实际上每一次就是对应的整个数列的第k小,因此可以直接预处理解决,接下来考虑如何找到这个点,可以直接用一个指针解决,然后就是简单的无旋treap操作:

    给定一个平衡树上节点,求它在当前序列中的下标,首先我们先将这个点到平衡树根节点的标记下传,使用递归解决,然后就直接根据BST的性质查找即可。

    其余的就是按照题意进行区间rotate,这是无旋treap的简单操作之一,不多赘述。

    代码中还有很多东西是可以优化的,例如不需要存储val,可以舍弃已经有序的区间等,如果你能做到的话,应该是轻松Rank1的节奏?

    #include <stdio.h>
    #include <algorithm>
    #define r register
    #define MN 100005
    #define getchar() (S==TT&&(TT=(S=BB)+fread(BB,1,1<<15,stdin),TT==S)?EOF:*S++)
    char BB[1<<15],*S=BB,*TT=BB;
    inline int in(){
        r int x=0; r bool f=0; r char c;
        for (;(c=getchar())<'0'||c>'9';f=c=='-');
        for (x=c-'0';(c=getchar())>='0'&&c<='9';x=(x<<3)+(x<<1)+c-'0');
        return f?-x:x;
    }
    namespace Treap{
        inline int Rand(){
            static int x=23333;
            return x^=x<<13,x^=x>>17,x^=x<<5;
        }
        struct node{
            node *ls,*rs,*fa;
            int val,sz,pri;bool rev;
            inline void reverse(){std::swap(ls,rs);if (ls) ls->rev^=1;if (rs) rs->rev^=1;rev=0;}
            inline void pushdown(){if (rev) reverse();}
            inline void combine(){
                sz=1;if (ls) sz+=ls->sz,ls->fa=this;
                if (rs) sz+=rs->sz,rs->fa=this;
            }
            node(int val):val(val){sz=1,pri=Rand(),rev=0,fa=ls=rs=NULL;}
        }*root,*pos[MN];    
        struct Droot{node *a,*b;};
        inline int Size(node *x){return x?x->sz:0;}
        node *merge(node *a,node *b){
            if (!a) return b;if (!b) return a;
            if (a->pri<b->pri){
                a->pushdown();
                a->rs=merge(a->rs,b);
                a->combine();return a;
            }else{
                b->pushdown();
                b->ls=merge(a,b->ls);
                b->combine();return b;
            }
        }
        Droot split(node *x,int k){
            if (!x) return (Droot){NULL,NULL};
            r Droot y;x->pushdown();
            if (k<=Size(x->ls)){
                y=split(x->ls,k);
                x->ls=y.b;x->combine();y.b=x;
            }else{
                y=split(x->rs,k-Size(x->ls)-1);
                x->rs=y.a;x->combine();y.a=x;
            }return y;
        }
        inline void Rotate(node *x){if (!x) return;Rotate(x->fa);x->pushdown();}
        inline int getpos(node *x){
            Rotate(x);r int res=Size(x->ls)+1;
            while (x->fa!=NULL){
                if (x->fa->rs==x) res+=Size(x->fa->ls)+1;x=x->fa;
            }return res;
        }
        inline int Get_Ans(int k){    
            r int ord=getpos(pos[k]);
            Droot x=split(root,ord);
            Droot y=split(x.a,k-1);
            y.b->rev^=1;root=merge(merge(y.a,y.b),x.b);
            return ord;
        }
    }using namespace Treap;
    struct things{
        int ord,val;
        inline bool operator <(const things &b)const{
            return val<b.val||(val==b.val&&ord<b.ord);
        }
    }a[MN];int n,val[MN],rnk[MN];
    void init(){
        n=in();
        for (int i=1; i<=n; ++i) val[i]=in(),a[i].ord=i,a[i].val=val[i];
        std::sort(a+1,a+n+1);for (r int i=1; i<=n; ++i) rnk[a[i].ord]=i;
        for (r int i=1; i<=n; ++i){
            pos[rnk[i]]=new node(val[i]);
            root=merge(root,pos[rnk[i]]);
        }
    }
    void solve(){for (r int i=1; i<=n; ++i) printf("%d ",Get_Ans(i));}
    int main(){init();solve();return 0;}
  • 相关阅读:
    (转)使用Regex.Replace只替换字符串一次
    转:div超出范围显示省略号
    ibatis This SQL map does not contain a MappedStatement
    ibatis 多表关联
    ibatis 传入xml Hashtable的应用以及动态字段出错的解决方法
    前台学习过程
    转:C#动态循环生成button怎么分别写他们的事
    在oracle DB 中通过JOB 调用存储过程
    sybase与oracle存储过程的写法对比
    游标Oracle游标使用大全
  • 原文地址:https://www.cnblogs.com/Melacau/p/BZOJ3506.html
Copyright © 2011-2022 走看看