• 洛谷P3165 [CQOI2014]排序机械臂


    题目描述

    为了把工厂中高低不等的物品按从低到高排好序,工程师发明了一种排序机械臂。它遵循一个简单的排序规则,第一次操作找到摄低的物品的位置P1,并把左起第一个至P1间的物品反序;第二次找到第二低的物品的位置P2,并把左起第二个至P2间的物品反序...最终所有的物品都会被排好序。

    上图给出_个示例,第_次操作前,菝低的物品在位置4,于是把第1至4的物品反序;第二次操作前,第二低的物品在位罝6,于是把第2至6的物品反序...

    你的任务便是编写一个程序,确定一个操作序列,即每次操作前第i低的物品所在位置Pi,以便机械臂工作。需要注意的是,如果有高度相同的物品,必须保证排序后它们的相对位置关系与初始时相同。

    输入输出格式

    输入格式:

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

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

    输出格式:

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

    输入输出样例

    输入样例#1: 复制

    6
    3 4 5 1 6 2

    输出样例#1: 复制

    4 6 4 5 6 6

    好变态的题啊。
    我们可以发现一个很显然的规律:
    (i-1)小的数一定不可能在第(i)次查询的区间里
    那么我们可以维护一下最小值,对于每次询问,在区间内找到最小值
    然后打上标记就好

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int MAXN=1e5+10;
    const int maxn=0x7fffff;
    const int INF=0x7fffffff;
    #define ls tree[x].ch[0]
    #define rs tree[x].ch[1]
    inline char nc()
    {
        static char buf[MAXN],*p1=buf,*p2=buf;
        return p1==p2&&(p2=(p1=buf)+fread(buf,1,MAXN,stdin),p1==p2)?EOF:*p1++;
    }
    inline int read()
    {
        char c=nc();int x=0,f=1;
        while(c<'0'||c>'9'){c=nc();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=nc();}
        return x*f;
    }
    int n,m;
    struct Q
    {
    	int val,pos;
    }a[MAXN];
    struct node
    {
        int tot,fa,ch[2],mn,mnpos,v;
        bool rev;
    }tree[MAXN];
    int tot,point;
    int root;
    int PosL,PosR;
    inline void connect(int x,int fa,bool how)
    {
        tree[x].fa=fa;
        tree[fa].ch[how]=x;
    }
    inline void update(int k)
    {
    	if(!k)	return ;
        tree[k].tot=tree[tree[k].ch[0]].tot+tree[tree[k].ch[1]].tot+1;
        tree[k].mn=tree[k].v; tree[k].mnpos=k;
        if(tree[k].ch[0]&&tree[tree[k].ch[0]].mn<tree[k].mn)	tree[k].mn=tree[tree[k].ch[0]].mn,tree[k].mnpos=tree[tree[k].ch[0]].mnpos;
    	if(tree[k].ch[1]&&tree[tree[k].ch[1]].mn<tree[k].mn)	tree[k].mn=tree[tree[k].ch[1]].mn,tree[k].mnpos=tree[tree[k].ch[1]].mnpos;
    }
    inline int BuildTree(int l,int r)
    {
        if(l>r) return 0;
        int mid=(l+r)>>1;
        if(l!=r)
        {
    	    connect(BuildTree(l,mid-1),mid,0);
    	    connect(BuildTree(mid+1,r),mid,1);	
    	}
        tree[mid].rev=0;
        tree[mid].mn=a[mid].val;
        tree[mid].v=a[mid].val;
        tree[mid].mnpos=mid;
        update(mid);
        return mid;
    }
    inline bool ident(int x)
    {
        return tree[tree[x].fa].ch[1]==x;
    }
    inline void pushdown(int x)
    {
        if(tree[x].rev)
        {
            swap(tree[x].ch[0],tree[x].ch[1]);
            tree[tree[x].ch[0]].rev^=1;
            tree[tree[x].ch[1]].rev^=1;	
            tree[x].rev=0;
        }
    }
    inline void rotate(int X)
    {
        pushdown(tree[X].fa);pushdown(X);
        int Y=tree[X].fa;
        if(Y==root)	root=X;
        int R=tree[Y].fa;
        bool Yson=ident(X);
        bool Rson=ident(Y);
        int B=tree[X].ch[Yson^1];
        connect(B,Y,Yson);
        connect(Y,X,Yson^1);
        connect(X,R,Rson);
        update(Y);update(X);
    }
    inline void splay(int x,int to)
    {
    	to=tree[to].fa;
        while(tree[x].fa!=to)
        {
            if(tree[tree[x].fa].fa==to)		rotate(x);
            else if(ident(x)==ident(tree[x].fa)) rotate(tree[x].fa),rotate(x);
            else rotate(x),rotate(x);
        }
        update(x);
    }
    int find(int x, int rk)
    {
        pushdown(x);//标记下传 
        if(tree[ls].tot+1==rk) return x;
        else if(tree[ls].tot >= rk) return find(ls, rk);
        else return find(rs, rk-tree[ls].tot-1);
    }
    const int comp(const Q a,const Q b)
    {
    	return a.val<b.val||(a.val==b.val&&a.pos<b.pos);
    }
    const int comp2(const Q a,const Q b)
    {
    	return a.pos<b.pos;
    }
    int QueryMin(int l,int r)
    {
    	int x1=find(root,l);
    	int x2=find(root,r+2);
    	splay(x1,root);
    	splay(x2,tree[x1].ch[1]);
    	return tree[ tree[x2].ch[0] ].mnpos;
    }
    inline void rever(int l,int r)
    {
    	int x1=find(root,l),x2=find(root,r+2);
    	splay(x1,root);splay(x2,tree[x1].ch[1]);
    	tree[tree[x2].ch[0]].rev^=1;
    }
    int main()
    {
    	#ifdef WIN32
        freopen("a.in","r",stdin);
        #else
    	#endif 
    	int n=read();
        a[1].val=a[n+2].val=INF;
        for(int i=2;i<=n+1;i++)	a[i].val=read(),a[i].pos=i;
        sort(a+2,a+n+2,comp);
        for(int i=2;i<=n+1;i++)	a[i].val=i-1;
        sort(a+2,a+n+2,comp2);
        //for(int i=1;i<=n+2;i++)	printf("%d ",a[i].pos);printf("
    ");
    	BuildTree(1,n+2);
    	root=(n+3)>>1;
    	for(int i=1;i<=n;i++)
    	{
    		int x=QueryMin(i,n);
    		splay(x,root);
    		int out=tree[tree[x].ch[0]].tot;
    		rever(i,out);
    		printf("%d ",out);
    	}
    }
    
  • 相关阅读:
    mac 终端 常用命令
    创办支持多种屏幕尺寸的Android应用
    java学习之部分笔记2
    java学习之部分笔记
    java学习之i/o
    java中String的用法
    java中List的用法
    java学习之Date的使用
    java学习之数据库
    C#中通过类来继承两个接口,父类实例化接口中的方法,子类继承父类,调用方法
  • 原文地址:https://www.cnblogs.com/zwfymqz/p/7899271.html
Copyright © 2020-2023  润新知