题目大意
对一个序列做k轮冒泡排序,输出最终序列。
做法
尝试计算每一个数的位移。
计算一个数前进的位数t等于在它前面比它大的数个数与k取min。
同样前面最大的t个数都会后退一格。
于是splay模拟这个过程统计每个位置的位移即可。
#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
const int maxn=200000+10;
int father[maxn],a[maxn],b[maxn],c[maxn],size[maxn],tree[maxn][2],ad[maxn],sta[maxn];
int i,j,k,l,t,n,m,tot,top,root;
int read(){
int x=0,f=1;
char ch=getchar();
while (ch<'0'||ch>'9'){
if (ch=='-') f=-1;
ch=getchar();
}
while (ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
int pd(int x){
return tree[father[x]][1]==x;
}
void update(int x){
size[x]=size[tree[x][0]]+size[tree[x][1]]+1;
}
void rotate(int x){
int y=father[x],z=pd(x);
father[x]=father[y];
if (father[y]) tree[father[y]][pd(y)]=x;
tree[y][z]=tree[x][1-z];
if (tree[x][1-z]) father[tree[x][1-z]]=y;
tree[x][1-z]=y;
father[y]=x;
update(y);
update(x);
}
void mark(int x,int v){
if (!x) return;
ad[x]+=v;
}
void clear(int x){
if (ad[x]){
mark(tree[x][0],ad[x]);
mark(tree[x][1],ad[x]);
c[x]+=ad[x];
ad[x]=0;
}
}
void remove(int x,int y){
top=0;
while (x!=y){
sta[++top]=x;
x=father[x];
}
while (top) clear(sta[top--]);
}
void splay(int x,int y){
remove(x,y);
while (father[x]!=y){
if (father[father[x]]!=y)
if (pd(x)==pd(father[x])) rotate(father[x]);else rotate(x);
rotate(x);
}
}
void insert(int &x,int y){
if (!x){
x=++tot;
update(x);
return;
}
if (a[y]<a[x]||a[y]==a[x]&&y<x){
insert(tree[x][0],y);
father[tree[x][0]]=x;
}
else{
insert(tree[x][1],y);
father[tree[x][1]]=x;
}
update(x);
}
int kth(int x,int y){
clear(x);
if (size[tree[x][0]]+1==y) return x;
if (size[tree[x][0]]+1<y) return kth(tree[x][1],y-size[tree[x][0]]-1);
else return kth(tree[x][0],y);
}
int rank(int x,int y){
if (!x) return 0;
clear(x);
if (a[x]<a[y]||a[x]==a[y]&&x<y) return rank(tree[x][1],y);
else return rank(tree[x][0],y)+size[tree[x][1]]+1;
}
int merge(int a,int b){
if (!a||!b) return a+b;
int j=kth(a,size[a]);
splay(j,0);
tree[j][1]=b;
father[b]=j;
update(j);
return j;
}
void write(int x){
if (!x){
putchar('0');
putchar('\n');
return;
}
top=0;
while (x){
sta[++top]=x%10;
x/=10;
}
while (top) putchar('0'+sta[top--]);
putchar('\n');
}
int main(){
freopen("fable.in","r",stdin);freopen("fable.out","w",stdout);
n=read();k=read();
fo(i,1,n){
a[i]=read();
insert(root,i);
splay(i,0);
root=i;
}
fd(i,n,1){
splay(i,0);
j=tree[i][0];l=tree[i][1];
tree[i][0]=tree[i][1]=0;
father[j]=father[l]=0;
root=merge(j,l);
t=rank(root,i);
t=min(t,k);
c[i]-=t;
if (!t) continue;
if (i-1==t) mark(root,1);
else{
j=kth(root,i-t-1);
splay(j,0);
mark(tree[j][1],1);
root=j;
}
}
fo(i,1,n) b[i+c[i]]=a[i];
fo(i,1,n) write(b[i]);
}