解析
感觉不至于黑的题。
然而我并不会做
did_idi 互不相同的时候直接无脑贪心即可,这样55分的好成绩就到手了。(交完发现可以骗到60)
滚榜级的良心分了属于是。
考虑有相同时如何做。
先把值降序排序,然后维护一棵线段树,存储每个点左侧还空余的位置。
按照 bfs序 枚举节点(其实就是1-n),每次找到空余位置不少于 sizsizsiz 的位置。
当有相等时选择占用最靠右的一个,这里我使用了离散化后堆存储下标来实现,感觉非常优美。
确定位置后位置之后的空余都要减去子树大小。
注意到,由于前面没有修改,我们实际上寻找的应该是满足后缀最小值不小于 sizsizsiz 的最左位置。
维护一个最小值,线段树二分即可实现。
记得算儿子的时候把父亲子树的影响删去。
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define ok debug("OK\n")
using namespace std;const int N=5e5+100;
const int mod=998244353;
const int C=26;inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)) {if(c=='-')f=-1;c=getchar();}while(isdigit(c)) {x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f;
}int n,m;#define mid ((l+r)>>1)
#define ls (k<<1)
#define rs (k<<1|1)
int mn[N<<2],laz[N<<2];
inline void pushup(int k){mn[k]=min(mn[ls],mn[rs]);return;
}
inline void add(int k,int w){mn[k]+=w;laz[k]+=w;
}
inline void pushdown(int k){int o=laz[k];laz[k]=0;if(!o) return;add(ls,o);add(rs,o);
}
void build(int k,int l,int r){if(l==r){mn[k]=l;return;}build(ls,l,mid);build(rs,mid+1,r);pushup(k);
}
int find(int k,int l,int r,int w){if(l==r){return mn[k]>=w?l:0;}pushdown(k);if(mn[rs]<w) return find(rs,mid+1,r,w);else{int d=find(ls,l,mid,w);return d?d:mid+1;}
}
void change(int k,int l,int r,int x,int y,int w){if(x<=l&&r<=y){add(k,w);return;}pushdown(k);if(x<=mid) change(ls,l,mid,x,y,w);if(y>mid) change(rs,mid+1,r,x,y,w);pushup(k);
}int d[N];
double k;
int fa[N],siz[N];
vector<int>v[N];
int w[N];priority_queue<int>id[N];
bool jd[N];
int q[N],cnt;
bool cmp(int x,int y){return x>y;
}
int pl[N];
signed main(){
#ifndef ONLINE_JUDGE//freopen("a.in","r",stdin);//freopen("a.out","w",stdout);
#endifscanf("%d %lf",&n,&k);for(int i=1;i<=n;i++) q[i]=d[i]=read(); cnt=n;sort(q+1,q+1+cnt);cnt=unique(q+1,q+1+cnt)-q-1;sort(d+1,d+1+n,cmp); for(int i=1;i<=n;i++){d[i]=lower_bound(q+1,q+1+cnt,d[i])-q;id[d[i]].push(i);//printf("i=%d d=%d\n",i,d[i]);}for(int i=n;i>=1;i--){siz[i]++;fa[i]=floor(i/k);siz[fa[i]]+=siz[i];}build(1,1,n);for(int i=1;i<=n;i++){int f=fa[i];if(f&&!jd[f]){jd[f]=1;change(1,1,n,pl[f],n,siz[f]-1);}int o=find(1,1,n,siz[i]);pl[i]=id[d[o]].top();//printf("i=%d fa=%d siz=%d find=%d pl=%d\n",i,fa[i],siz[i],o,pl[i]);id[d[o]].pop();w[i]=q[d[pl[i]]];change(1,1,n,pl[i],n,-siz[i]);}for(int i=1;i<=n;i++) printf("%d ",q[d[pl[i]]]);return 0;
}
/*
8 3.000
31 15 2 54 97 65 46 61
*/