很容易发现关系可以形成一个树形结构,一个点的子树中的点权都要比它大
则我们给一个点赋值的时候要给它的siz那么多点预留一些点,我们维护f[i]表示i点还可选的点个数,则每次都用线段树维护一下就行了
要容斥一下,如果这个点的father有点权了就要减去这个点的信息
Code:
#include<bits/stdc++.h>
#define ls tr[k].l
#define rs tr[k].r
#define mid ((ls+rs)>>1)
using namespace std;
inline int read(){
int res=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
return res*f;
}
int n;
double k;
const int N=6e5+5;
int nxt[N],fa[N],siz[N],a[N],ans[N];
namespace segtree{
struct seg{int l,r,minn,add;}tr[N<<2];
inline void pushup(int k){tr[k].minn=min(tr[k<<1].minn,tr[k<<1|1].minn);}
inline void pushadd(int k,int v){tr[k].add+=v;tr[k].minn+=v;}
inline void pushdown(int k){if(tr[k].add){pushadd(k<<1,tr[k].add);pushadd(k<<1|1,tr[k].add);tr[k].add=0;}}
void build(int k,int l,int r){
ls=l,rs=r;tr[k].add=0;
if(l==r) {tr[k].minn=l;return;}
build(k<<1,l,mid);build(k<<1|1,mid+1,r);
pushup(k);
}
void update(int k,int ql,int qr,int v){
if(ls>qr || rs<ql) return;
if(ql<=ls && rs<=qr) return pushadd(k,v);
pushdown(k);
if(qr<=mid) update(k<<1,ql,qr,v);
else if(ql>mid) update(k<<1|1,ql,qr,v);
else update(k<<1,ql,mid,v),update(k<<1|1,mid+1,qr,v);
pushup(k);
}
int query(int k,int ql,int qr,int v){
if(ql==qr) return tr[k].minn>=v?ql:ql+1;
pushdown(k);int midd=(ql+qr)>>1;
if(v<=tr[k<<1|1].minn) return query(k<<1,ql,midd,v);
else return query(k<<1|1,midd+1,qr,v);
}
}
using namespace segtree;
inline bool cmp(int a,int b){return a>b;}
int main(){
n=read();scanf("%lf",&k);
for(int i=1;i<=n;i++) a[i]=read();
sort(a+1,a+n+1,cmp);
for(int i=n;i;i--){
nxt[i]=i,fa[i]=floor(1.*i/k);
++siz[i];siz[fa[i]]+=siz[i];
if(a[i]==a[i+1]) nxt[i]=nxt[i+1];
}
build(1,1,n);
for(int i=1;i<=n;i++){
if (fa[i] && fa[i]!=fa[i-1]) update(1,ans[fa[i]],n,siz[fa[i]]-1);
int p=nxt[query(1,1,n,siz[i])];ans[i]=p;
update(1,p,n,-siz[i]);
}
for(int i=1;i<=n;i++) cout<<a[ans[i]]<<" ";
return 0;
}