这题的建模有点不太一样,是按结点横坐标赋予键值的
同时每次rotate和splay时都要注意下往上往下更新
/*
先建立好splay tree,将结点按num/输入顺序排序,遍历时每次将当前结点提到根节点,输出其在splay树中排第几个
然后rev左子树,最后remove
*/
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#include<algorithm>
#define maxn 100005
struct A{
int num,id;
bool operator < (const A &a) const {
if(num==a.num) return id<a.id;
return num<a.num;
}
}a[maxn];
int pre[maxn],ch[maxn][],size[maxn],keys[maxn],tot,root,n;
int rev[maxn];
inline void pushup(int r){
size[r]=size[ch[r][]]+size[ch[r][]]+;
}
void update(int r){//就是交换r的两个子区间
if(!r) return;
else {
swap(ch[r][],ch[r][]);
rev[r]^=;
}
}
inline void pushdown(int r){
if(rev[r]){//把左右子树rev
update(ch[r][]);
update(ch[r][]);
rev[r]=;
}
}
inline void newnode(int &r,int fa,int key){
r=key;
pre[r]=fa;
ch[r][]=ch[r][]=;
size[r]=;
keys[r]=key;
rev[r]=;
}
void build(int &r,int L,int R,int fa){
if(L>R) return;
int m=L+R>>;
newnode(r,fa,m);
build(ch[r][],L,m-,r);
build(ch[r][],m+,R,r);
pushup(r);
}
void init(){
root=tot=;
ch[root][]=ch[root][]=;
size[root]=;
rev[root]=;
build(root,,n,);
}
//rotate操作只会改变r,fa,ch[r][kind]三个结点
void rotate(int x,int kind){
int fa=pre[x];
pushdown(fa);
pushdown(x);
ch[fa][!kind]=ch[x][kind];
pre[ch[x][kind]]=fa;
if(pre[fa])
ch[pre[fa]][ch[pre[fa]][]==fa]=x;
pre[x]=pre[fa];
pre[fa]=x;
ch[x][kind]=fa;
pushup(fa);
pushup(x);
}
void splay(int r,int goal){
pushdown(r);
while(pre[r]!=goal){
if(pre[pre[r]]==goal){
pushdown(pre[r]);
pushdown(r);
rotate(r,ch[pre[r]][]==r);
}
else {
pushdown(pre[pre[r]]);
pushdown(pre[r]);
pushdown(r);
int fa=pre[r];
int kind=(ch[pre[fa]][]==fa);
if(ch[fa][kind]==r){//方向相反
rotate(r,!kind);
rotate(r,kind);
}
else {
rotate(fa,kind);
rotate(r,kind);
}
}
}
if(goal==) root=r;
pushup(r);
}
void remove(){//删掉根节点
if(ch[root][]==){
root=ch[root][];
pre[root]=;
}
else {
pushdown(root);
int tmp=ch[root][];
while(ch[tmp][])
pushdown(tmp),tmp=ch[tmp][];
splay(tmp,root);
ch[tmp][]=ch[root][];
pre[ch[root][]]=tmp;
root=tmp;
pre[root]=;
pushup(root);
}
} int main(){
while(scanf("%d",&n) && n){
init();
for(int i=;i<=n;i++)
scanf("%d",&a[i].num),a[i].id=i;
sort(a+,a++n);
for(int i=;i<n;i++){
splay(a[i].id,);//按权值大小遍历点
update(ch[root][]);//逆转区间
printf("%d ",i+size[ch[root][]]);//输出结点在当前伸展树中排的序号
remove();
}
printf("%d\n",n);
}
return ;
}