zoukankan      html  css  js  c++  java
  • BZOJ3506: [Cqoi2014]排序机械臂

    BZOJ3506: [Cqoi2014]排序机械臂

    额,$BZOJ$上没有题面。。。

    本蒟蒻表示没钱氪金。。。

    这里附上洛谷的题面:

    洛谷P3165 [CQOI2014]排序机械臂

    题目描述

    为了把工厂中高低不等的物品按从低到高排好序,工程师发明了一种排序机械臂。

    它遵循一个简单的排序规则,第一次操作找到高度最低的物品的位置 $P_1$ ,并把左起第一个物品至 $P_1$ 间的物品 (即区间 $[1,P_1]$间的物品) 反序;第二次找到第二低的物品的位置 $P_2$ ,并把左起第二个至 $P_2$ 间的物品 (即区间 $[2,P_2]$ 间的物品) 反序……最终所有的物品都会被排好序。

    样例说明

    上图给出有六个物品的示例,第一次操作前,高度最低的物品在位置 $4$ ,于是把第一至第四的物品反序;第二次操作前,第二低的物品在位罝六,于是把第二至六的物品反序……

    你的任务便是编写一个程序,确定一个操作序列,即每次操作前第$ i$ 低的物品所在位置$ P_i$,以便机械臂工作。

    需要注意的是,如果有高度相同的物品,必须保证排序后它们的相对位置关系与初始时相同。

    输入输出格式

    输入格式:

    第一行包含正整数n,表示需要排序的物品数星。

    第二行包含n个空格分隔的整数$P_i$,表示每个物品的高度。

    输出格式:

    输出一行包含n个空格分隔的整数Pi。

    输入输出样例

    输入样例#1: 复制
    6
    3 4 5 1 6 2
    输出样例#1: 复制
    4 6 4 5 6 6

    说明

    N<=100000

    Pi<=10^7


    题解Here!

    看到区间翻转——区间神器$Splay$!

    但是!高度是无序的,而$Splay$是有序的,怎么办呢?

    我们可以用结构体存高度与 下标,然后排序。

    于是高度就可以丢一边了。。。

    具体看代码中的$splay::reverse$ 。

    注意:

    1. 头尾设两个哨兵节点。
    2. $splay$每次都要$pushdown$一次(巨坑)!

    附代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #define MAXN 100010
    #define MAX 999999999
    using namespace std;
    int n,size=1,root=0;
    struct node{
        int x,id;
    }b[MAXN];
    namespace splay{
        struct Splay{
            int f,s,flag,son[2];
            int v;
        }a[MAXN];
        inline void clean(int rt){
            a[rt].son[0]=a[rt].son[1]=a[rt].f=a[rt].s=a[rt].flag=a[rt].v=0;
        }
        inline void pushup(int rt){
            if(!rt)return;
            a[rt].s=a[a[rt].son[0]].s+a[a[rt].son[1]].s+1;
        }
        inline void pushdown(int rt){
            if(!rt||!a[rt].flag)return;
            a[a[rt].son[0]].flag^=1;a[a[rt].son[1]].flag^=1;a[rt].flag^=1;
            swap(a[rt].son[0],a[rt].son[1]);
        }
        inline void turn(int rt,int k){
            int x=a[rt].f,y=a[x].f;
            a[x].son[k^1]=a[rt].son[k];
            if(a[rt].son[k])a[a[rt].son[k]].f=x;
            a[rt].f=y;
            if(y)a[y].son[a[y].son[1]==x]=rt;
            a[x].f=rt;
            a[rt].son[k]=x;
            pushup(x);pushup(rt);
        }
        void splay(int rt,int ancestry){
            while(a[rt].f!=ancestry){
                int x=a[rt].f,y=a[x].f;
                pushdown(y);pushdown(x);pushdown(rt);
                if(y==ancestry)turn(rt,a[x].son[0]==rt);
                else{
                    int k=a[y].son[0]==x?1:0;
                    if(a[x].son[k]==rt){turn(rt,k^1);turn(rt,k);}
                    else{turn(x,k);turn(rt,k);}
                }
            }
            if(ancestry==0)root=rt;
        }
        inline int newnode(int x){
            int rt=size++;
            clean(rt);
            a[rt].v=x;a[rt].s=1;
            return rt;
        }
        int buildtree(int l,int r){
            if(l>r)return 0;
            int mid=l+r>>1,lson=0,rson=0;
            lson=buildtree(l,mid-1);
            int rt=newnode(b[mid].x);
            rson=buildtree(mid+1,r);
            a[rt].son[0]=lson;
            a[rt].son[1]=rson;
            if(lson)a[lson].f=rt;
            if(rson)a[rson].f=rt;
            pushup(rt);
            return rt;
        }
        int kth(int rt,int k){
            if(a[rt].s<k)return 0;
            while(1){
                pushdown(rt);
                int y=a[rt].son[0];
                if(k>a[y].s+1){
                    k-=a[y].s+1;
                    rt=a[rt].son[1];
                }
                else if(k<=a[y].s)rt=y;
                else return rt;
            }
        }
        inline void reverse(int i){
            splay(b[i].id+1,0);
            int s=a[a[root].son[0]].s;
            printf("%d ",s);
            int front=kth(root,i),next=kth(root,s+2);
            splay(front,0);splay(next,front);
            a[a[next].son[0]].flag^=1;
        }
    }
    inline int read(){
    	int date=0,w=1;char c=0;
    	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
    	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
    	return date*w;
    }
    bool cmp(const node &x,const node &y){
        if(x.x==y.x)return x.id<y.id;
        return x.x<y.x;
    }
    void init(){
        n=read();
        for(int i=1;i<=n;i++){
            b[i].x=read();
            b[i].id=i;
        }
        b[0].x=-MAX;b[0].id=1;
        b[n+1].x=MAX;b[n+1].id=n+1;
        sort(b+1,b+n+1,cmp);
        root=splay::buildtree(0,n+1);
        for(int i=1;i<=n-1;i++)splay::reverse(i);
        printf("%d
    ",n);
    }
    int main(){
        init();
    	return 0;
    }
    
  • 相关阅读:
    Linux Shell编程(3)——运行shell脚本
    Linux Shell编程(2)——第一个shell程序
    Linux Shell编程(1)——shell编程简介
    做“程序员”,不做“码农”,有哪些好办法?
    玩转大数据,顺利渡过34岁裁退危机!
    Google IO 2017为我们带来了什么
    《经验之谈》想要做好SEO推广必知要事,峰任策划告诉您。
    5月17日云栖精选夜读:分布式大数据系统巧实现,全局数据调度管理不再难
    程序员转型发展:拆除这些墙,才会发现更蓝的天空
    敢问路在何方?程序员转行应该卖水果还是卖烧饼
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/9940392.html
Copyright © 2011-2022 走看看