Description
为了把工厂中 高低不等的物品按从低到高排好序,工程师发明了一种排序机械臂。它遵循一个简单的排序规则,第一次操作找到最低的物品位置P1,并把从左起第1个至第P1个之间的物品反序;第二次找到第二低的物品的位置P2,并把左起第二个至第P2个之间的物品反序……最终所有的物品都会被排好序。
上图给出一个示例,第一次操作前,最低物品在位置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<bits/stdc++.h>
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<kth)kth-=siz[Ls(x)]+1,x=rs(x);
else x=Ls(x);
}
return x;
}
inline void reverse(int L,int r){
int Lp=FindP(L),rp=FindP(r);
splay(Lp,1),splay(rp,0);
rev[Ls(rp)]^=1;
}
}sp;
bool cmp(const Pair&A,const Pair&B){
return A.fir^B.fir?A.fir<B.fir:A.sec<B.sec;
}
inline void init(){
scanf("%d",&n);
a[1]=(Pair){-0x3f3f3f3f,1};
Inc(i,2,n+1)a[i]=(Pair){get(),i};
a[n+2]=(Pair){0x3f3f3f3f,n+2};
sort(a+1,a+n+3,cmp);
sp.rt=sp.build(1,n+2);
}
inline void solv(){
Inc(i,2,n+1){
sp.splay(a[i].sec,1);//中序遍历即区间位置
cout<<sp.siz[sp.Ls(sp.rt)]<<' ';//哨兵的影响
sp.reverse(i-1,sp.siz[sp.Ls(sp.rt)]+2);//+2你懂
}
}
int main(){
init();
solv();
return 0;
}