Fable
来源:互联网 发布:python作品 编辑:程序博客网 时间:2024/05/18 07:44
题目大意
对一个序列做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]);}