注意到这个森林的bfs序就是从(1)到(n),然后要使得字典序最大,那么显然要从(1)到(n)依次考虑放什么数.有一个(d)全部不同的贪心,就是维护某个点子树内可用的权值集合,首先这个点只能取最小的,然后按顺序枚举儿子,要使得字典序最大,那就要让前面的点能取的权值尽量大,又因为(d_xge d_{fa_x}),所以一个点选的位置最靠后可以在从小到大倒数第(sz_x)个位置,然后后面的值就分给他的儿子子树.删掉后面一些位置接着做就行了
注意有(d)相等的时候这个是假的,因为某个点可以通过将自己取值所在位置的前移,使得自己取值尽可能大的情况下后面一个点取值可以更大.不过现在貌似没有一个可以直接瞎贪心的做法
考虑先不决定一个点子树内到底取哪些点.先把所有权值从小到大排序,把相同的数合并,然后对每个位置记一个(f_i)表示这个位置以及后面有多少个数没被选定.每次要选(x)的取值的时候,那么选的位置一定要满足(f_ige sz_x),又因为要使得字典序最大,所以就是要选满足(f_ige sz_x)并且权值最大(位置最右边)的位置,选了这个位置就是这个点的值,然后后面还要留出一些位置给子树选,所以(f_1)到(f_i)要减去(sz_x).然后模拟这个过程(n)次即可得到答案
注意一下,首先(f_i)是单调不增的,因为(f_i)本质上是一个后缀和,所以说真正的(f_i)应该是(min_{j=1}^{i} f_j);并且在做到一个点的时候,如果它是其父亲的第一个儿子,那么要消除它父亲的影响(也就是(f_1)到(f_{ans_{fa_x}})加上(sz_{fa_x}-1)),因为那个(sz_{fa_x}-1)是被父亲占用的,现在我们要把这一部分留给子树去选
// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define LL long long
#define uLL unsigned long long
#define db double
using namespace std;
const int N=5e5+10;
int rd()
{
int x=0,w=1;char ch=0;
while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*w;
}
#define mid ((l+r)>>1)
int mi[N<<2],tg[N<<2];
void psup(int o){mi[o]=min(mi[o<<1],mi[o<<1|1]);}
void ad(int o,int x){mi[o]+=x,tg[o]+=x;}
void psdn(int o){if(tg[o]) ad(o<<1,tg[o]),ad(o<<1|1,tg[o]),tg[o]=0;}
void modif(int o,int l,int r,int ll,int rr,int x)
{
if(ll<=l&&r<=rr){ad(o,x);return;}
psdn(o);
if(ll<=mid) modif(o<<1,l,mid,ll,rr,x);
if(rr>mid) modif(o<<1|1,mid+1,r,ll,rr,x);
psup(o);
}
int quer(int o,int l,int r,int w)
{
if(l==r) return l-(mi[o]<w);
psdn(o);
int an=mi[o<<1]>=w?quer(o<<1|1,mid+1,r,w):quer(o<<1,l,mid,w);
psup(o);
return an;
}
db kk;
int n,a[N],an[N],b[N],m,sz[N],fa[N];
bool v[N];
void bui(int o,int l,int r)
{
if(l==r){mi[o]=b[l];return;}
bui(o<<1,l,mid),bui(o<<1|1,mid+1,r);
psup(o);
}
int main()
{
n=rd();
scanf("%lf",&kk);
for(int i=1;i<=n;++i) a[i]=rd();
sort(a+1,a+n+1);
for(int i=1;i<=n;++i)
{
if(a[i]!=a[i-1]) ++m;
++b[m];
}
for(int i=m;i;--i) b[i]+=b[i+1];
bui(1,1,m);
unique(a+1,a+n+1);
for(int i=1;i<=n;++i)
{
fa[i]=(int)((db)i/kk);
sz[i]=1;
}
for(int i=n;i;--i)
sz[fa[i]]+=sz[i];
for(int i=1;i<=n;++i)
{
if(!v[fa[i]])
if(an[fa[i]]) modif(1,1,m,1,an[fa[i]],sz[fa[i]]-1);
v[fa[i]]=1;
int p=quer(1,1,m,sz[i]);
modif(1,1,m,1,p,-sz[i]);
printf("%d ",a[an[i]=p]);
}
return 0;
}