从1到n枚举,逐位确定。
首先可以把关系树建出来,一个点的权值要大于等于父节点的权值。
如果没有相同数字的,第 i i 以及它子树种的点会选择 这个区间里的数,选完后把这个区间删去,继续考虑 i+1 i + 1
如果有重复的数字,那么第 i i 个点会选择第 大的数字,但是它的子树中的点选择的区间就不能确定。
令 ai a i 表示大于等于 i i 的可以选择的数的个数, 表示已经选了多少个大于等于 i i 的数
那么如果当前考虑 点, i i 点选择的数为 ( p p 肯定会尽可能的大),那么我们就会选择 个大于等于 p p 的数。
可以发现,如果 能选择 p p ,那么对于任何一个小于等于 的 j j 都满足
也就是 sizei≤aj−bj s i z e i ≤ a j − b j ,用线段树记录 aj−bj a j − b j ,然后在线段树上二分一下 p p <script type="math/tex" id="MathJax-Element-92">p</script> 就可以了
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <vector>
#define ALL(x) (x).begin(),(x).end()
using namespace std;
typedef pair<int,int> pii;
const int N=500010;
int n,cnt,b[N],a[N],G[N],size[N],ans[N],son[N],dpt[N],fa[N];
double k;
struct edge{
int t,nx;
}E[N];
vector<int> sb;
inline void addedge(int x,int y){
E[++cnt].t=y; E[cnt].nx=G[x]; G[x]=cnt;
}
void dfs(int x){
size[x]=1;
for(int i=G[x];i;i=E[i].nx){
dpt[E[i].t]=dpt[x]+1;
dfs(E[i].t);
size[x]+=size[E[i].t];
fa[E[i].t]=x;
}
}
int mn[N<<2],tag[N<<2];
inline void Up(int g){
mn[g]=min(mn[g<<1]+tag[g<<1],mn[g<<1|1]+tag[g<<1|1]);
}
void build(int g,int l,int r){
if(l==r) return mn[g]=b[l],void();
int mid=l+r>>1;
build(g<<1,l,mid); build(g<<1|1,mid+1,r);
Up(g);
}
vector<int> Q[N];
void Modify(int g,int l,int r,int L,int R,int x){
if(l==L && r==R) return tag[g]+=x,void();
int mid=L+R>>1;
if(r<=mid) Modify(g<<1,l,r,L,mid,x);
else if(l>mid) Modify(g<<1|1,l,r,mid+1,R,x);
else Modify(g<<1,l,mid,L,mid,x),Modify(g<<1|1,mid+1,r,mid+1,R,x);
Up(g);
}
int Query(int s){
int g=1,l=1,r=n,ret;
while(l<r){
int mid=l+r>>1; s-=tag[g];
if(mn[g<<1]+tag[g<<1]<s) r=mid,g=g<<1;
else l=mid+1,g=g<<1|1,ret=mid;
}
if(mn[g]+tag[g]>=s) return l;
return ret;
}
int main(){
scanf("%d%lf",&n,&k);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]),sb.push_back(a[i]);
sb.push_back(0); sort(ALL(sb)); sb.erase(unique(ALL(sb)),sb.end());
for(int i=1;i<=n;i++) a[i]=lower_bound(ALL(sb),a[i])-sb.begin();
for(int i=1;i<=n;i++) addedge(i/k,i);
dfs(0);
for(int i=1;i<=n;i++) b[a[i]]++;
for(int i=n;i;i--) b[i]+=b[i+1];
build(1,1,n);
for(int i=1;i<=n;i++) Q[dpt[i]].push_back(i);
for(int d=1;d<=dpt[n];d++){
for(int i=0;i<Q[d].size();i++){
if(d>1 && (i==0 || fa[Q[d][i]]!=fa[Q[d][i-1]]))
Modify(1,1,ans[fa[Q[d][i]]],1,n,size[fa[Q[d][i]]]-1);
int u=Q[d][i],p=Query(size[u]);
ans[u]=p; Modify(1,1,p,1,n,-size[u]);
}
}
for(int i=1;i<=n;i++) printf("%d ",sb[ans[i]]);
return 0;
}