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]);}