https://www.lydsy.com/JudgeOnline/problem.php?id=5249php
把樹建出來ios
若是全部的d互不相同,後續遍歷便可git
如今有的d相同spa
將d從小到大排序,考慮如何將這n個數填進樹裏code
至關與爲x的子樹預訂d序列中的一段blog
並且當且這個d填的位置越靠後越好排序
CTSC試機現場發題解,真爽。。。get
#include<cmath> #include<cstdio> #include<iostream> #include<algorithm> using namespace std; #define N 500001 int d[N],ans[N]; int siz[N]; int front[N],nxt[N],to[N],tot; int sum[N<<2]; void read(int &x) { x=0; char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); } } void add(int u,int v) { to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; siz[u]+=siz[v]; } void change(int k,int l,int r,int pos,int w) { if(l==r) { sum[k]+=w; return; } int mid=l+r>>1; if(pos<=mid) change(k<<1,l,mid,pos,w); else change(k<<1|1,mid+1,r,pos,w); sum[k]=sum[k<<1]+sum[k<<1|1]; } int find(int k,int l,int r,int s) { if(l==r) return l; int mid=l+r>>1; if(s<=sum[k<<1|1]) return find(k<<1|1,mid+1,r,s); return find(k<<1,l,mid,s-sum[k<<1|1]); } int main() { int n; double k; read(n); scanf("%lf",&k); for(int i=1;i<=n;++i) read(d[i]); sort(d+1,d+n+1); for(int i=1;i<=n;++i) siz[i]=1; for(int i=n;i;--i) add(i/k,i); for(int i=front[0];i;i=nxt[i]) change(1,1,n,to[i],siz[to[i]]); int j=1,t; for(int i=1;i<=n;i=j) { while(j<=n && d[i]==d[j]) j++; for(int l=j-i;l;--l) { t=find(1,1,n,l); ans[t]=d[i]; change(1,1,n,t,-siz[t]); for(int h=front[t];h;h=nxt[h]) change(1,1,n,to[h],siz[to[h]]); } } for(int i=1;i<=n;++i) printf("%d ",ans[i]); return 0; }