题目描述
给你一个序列,第i次操作是把第i个数到第i小的数这段区间翻转,即第i次操作把第i小的数一次翻转到第i个位置,最终序列会变成升序的(注意:如果有相同的数,那么在初始序列中靠前的在最终序列也靠前,即相同的数相对位置不变),每次操作前输出第i小的数所在的位置。
题解:
如果每次直接找整个数列第i小的数,需要树套树,其实,只要每次把第i个数翻转到第i个位置后,下一次操作需要翻转的数就是剩下的数中最小的,而只要维护两个标记,分别表示子树中最小的数和最小的数的位置,就可以实现找到最小的数,所以,只要每次翻转后都把最小的数删除即可。要维护的是序列,只要用SplayTree即可。
代码如下:
#include<cstdio>
#include<algorithm>
#include<cmath>
#define maxn 100006
using namespace std;
struct node{
node* ch[2];
int key,flip,cnt,M,Min;
void maintain(){
cnt=ch[0]->cnt+1+ch[1]->cnt;
Min=min(min(ch[0]->Min,key),ch[1]->Min);
if(Min==ch[0]->Min)M=ch[0]->M;else
if(Min==key)M=ch[0]->cnt+1;else
M=ch[0]->cnt+1+ch[1]->M;
}
void add(){
M=cnt-M+1;swap(ch[0],ch[1]);flip^=1;
}
void pushdown(){
if(flip)ch[0]->add(),ch[1]->add(),flip=0;
}
int cmp(int &k){
if(k< ch[0]->cnt+1)return 0;
if(k==ch[0]->cnt+1)return -1;
k-=ch[0]->cnt+1;return 1;
}
}nul;
struct data{
int x,id;
bool operator <(const data&b)const{
return id<b.id;
}
}a[maxn];
typedef node* pnode;
pnode null=&nul;
int _read(){
int sum=0;char ch=getchar();
while(!(ch>='0'&&ch<='9'))ch=getchar();
while(ch>='0'&&ch<='9')sum=sum*10+ch-48,ch=getchar();
return sum;
}
pnode newnode(int k){
pnode p=new node;p->key=k;p->cnt=1;p->flip=0;p->ch[0]=p->ch[1]=null;
p->Min=k;p->M=1;
return p;
}
void rot(pnode &p,int d){
pnode k=p->ch[d^1];p->ch[d^1]=k->ch[d];k->ch[d]=p;
p->maintain();k->maintain();p=k;
}
void splay(pnode &p,int k){
p->pushdown();
int d1=p->cmp(k);
if(d1!=-1){
p->ch[d1]->pushdown();int d2=p->ch[d1]->cmp(k);
if(d2!=-1){
splay(p->ch[d1]->ch[d2],k);
if(d1==d2)rot(p,d1^1);
else rot(p->ch[d1],d2^1);
}
rot(p,d1^1);
}
}
pnode build(int l,int r,data *arr){
if(l>r)return null;
int mid=(l+r)>>1;
pnode p=newnode((arr+mid)->x);
p->ch[0]=build(l,mid-1,arr);p->ch[1]=build(mid+1,r,arr);
p->maintain();
return p;
}
bool cmp(data i,data j){
return (i.x<j.x)|((i.x==j.x)&&(i.id<j.id));
}
int n;
int main(){
freopen("sort.in","r",stdin);
freopen("sort.out","w",stdout);
null->ch[0]=null->ch[1]=null;null->cnt=0;null->Min=1e9;
while(n=_read()){
for(int i=1;i<=n;i++)a[i].x=_read(),a[i].id=i;a[0].x=a[n+1].x=1e9;
sort(a+1,a+1+n,cmp);
for(int i=1;i<=n;i++)a[i].x=i;
sort(a+1,a+1+n);
pnode rt=build(0,n+1,a);
for(int i=1;i<n;i++){
printf("%d ",rt->M+i-2);
splay(rt,1);splay(rt->ch[1],rt->ch[1]->M+1);
rt->ch[1]->ch[0]->add();rt->ch[1]->ch[0]->pushdown();
splay(rt->ch[1],2);
delete rt->ch[1]->ch[0];rt->ch[1]->ch[0]=null;rt->ch[1]->maintain();rt->maintain();
}printf("%d\n",n);
}
return 0;
}