CQOI2014 排序机械臂

Description

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

CQOI2014 排序机械臂_第1张图片

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

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

Input

第一行包含一个正整数n,表示需要排序的物品数量。 
第二行包含n和空格分隔的整数ai,表示每个物品的高度。

Output

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

Sample Input

样例输入1:

6

3 4 5 1 6 2

样例输入2:

4

3 3 2 1

Sample Output

样例输出1:

4 6 4 5 6 6

样例输出2:

4 2 4 4

Hint

对于30%的数据,1<=n<=1000 
对于100%的数据,1<=n<=100000,1<=ai<=2*10^9

调了一个中午,发现不能用新点表示下标。。。。

讲下思路,因为发现询问和高度没有关系,而且splay维护区间后不能同时维护第k大值,于是我们想到排序,这样就符合题目的第i大要求,但是这样做必须要求原序列下标和splay下标严格对应= =

#include
using namespace std;
inline int get(){register int re=0,f=1;register char c;while(c=getchar(),(c>='0'&&c<='9')^1)f=c^'-';while(re=(re<<1)+(re<<3)+(c^48),c=getchar(),(c>='0'&&c<='9'));return f?re:-re;}
#define Inc(i,L,R) for(register int i=(L);i<=(R);++i)
#define Red(j,R,L) for(register int j=(R);j>=(L);--j)
const int N = 1e5+10;
struct Pair{
	int fir,sec;//权值,位置 
}a[N];
int n;
struct Splay{
	bool rev[N];
	int k[N],siz[N];
	int rt,cnt,p[N],ch[N][2];
	#define Ls(v) ch[v][0]
	#define rs(v) ch[v][1]
	#define sum(v) siz[v]=siz[Ls(v)]+siz[rs(v)]+1
	inline void pushdown(int x){
		if(rev[x]){
			rev[Ls(x)]^=1,rev[rs(x)]^=1;
			swap(Ls(x),rs(x));
			rev[x]=0;
		}
	}
	inline void rot(int x){
		int f=p[x],gf=p[f],type=ch[f][1]==x,son=ch[x][!type];
		ch[p[son]=f][type]=son,sum(f);
		ch[p[f]=x][!type]=f,sum(x);
		ch[p[x]=gf][ch[gf][1]==f]=x;
	}
	inline void splay(int x,bool flag){
		while(p[x]){
			if(!flag&&x==rs(rt))break;
			if(p[p[x]])pushdown(p[p[x]]);
			if(p[x])pushdown(p[x]);
			if(x)pushdown(x);
			if(flag&&p[p[x]]&&((ch[p[p[x]]][1]==p[x])==(ch[p[x]][1]==x)))rot(p[x]);
			else if(!flag&&p[x]!=rs(rt)&&((ch[p[p[x]]][1]==p[x])==(ch[p[x]][1]==x)))rot(p[x]);
			rot(x);
		}
		if(flag)rt=x;
	}
	inline int build(int L,int r){
		if(L>r)return 0;
		int Mid=L+r>>1;//用位置当下标 
		siz[Mid]=1;
		Ls(Mid)=build(L,Mid-1);
		rs(Mid)=build(Mid+1,r);
		sum(Mid);
		if(Ls(Mid))p[Ls(Mid)]=Mid;
		if(rs(Mid))p[rs(Mid)]=Mid;
		return Mid;
	}
	inline int FindP(int kth){
		int x=rt;
		while(1){
			pushdown(x);
			if(siz[Ls(x)]+1==kth)break;
			if(siz[Ls(x)]+1

 

你可能感兴趣的:(数据结构,splay)