题意:
分析:
- 暴力:
对于 (d_i) 互不相同的情况,排序后从小到大给每个点分配子树大小的后缀,期望得分:50pts
- 正解:
可能存在一种情况就是,有一个子树内的较大值可以和另一个作为根的点互换,不改变大小关系的同时使得值更大,所以我们考虑不直接给每个点分值了,而是考虑有多少个大于 x 的值已经被选了,这样相当于发生了互换
具体来说就是,我们对于每一个值个数为 (cnt_i) 表示大于等于 i 的能选的数有多少个,每当我们选择了某个根为 (x) ,也就是说对于小于等于 (x) 的值,能选的数全部减少了 (siz_i) ,而由于 (cnt) 是单调不增的,也就是说能选的数只会越来越少,所以我们每次对于一个点 (rt) 我们要找到一个最大的 (x) 满足 (min {cnt_1,cnt_2dots cnt_x}ge siz_{rt}) ,然后给 (cnt_1dots cnt_x) 区间减 (siz_{rt})
区间修改需要线段树,然后每次在线段树上二分找最大的 (x) 就行了
分析:
#include<bits/stdc++.h>
#define inl inline
#define reg register
#define lc rt<<1
#define rc rt<<1|1
using namespace std;
namespace zzc
{
typedef long long ll;
inl ll read()
{
ll x=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)) {x=x*10+ch-48;ch=getchar();}
return x*f;
}
const ll maxn = 5e5+5;
ll n,cnt;
double k;
ll fa[maxn],ans[maxn],siz[maxn],t[maxn],val[maxn<<2],a[maxn],b[maxn],tag[maxn<<2];
bool vis[maxn];
void pushdown(int rt)
{
if(tag[rt])
{
val[lc]+=tag[rt];tag[lc]+=tag[rt];
val[rc]+=tag[rt];tag[rc]+=tag[rt];
tag[rt]=0;
}
}
void pushup(int rt)
{
val[rt]=min(val[lc],val[rc]);
}
void build(int rt,int l,int r)
{
if(l==r)
{
val[rt]=t[l];
return ;
}
int mid=(l+r)>>1;
build(lc,l,mid);build(rc,mid+1,r);
pushup(rt);
}
void modify(int rt,int l,int r,int ql,int qr,int w)
{
if(ql<=l&&r<=qr)
{
val[rt]+=w;
tag[rt]+=w;
return ;
}
pushdown(rt);
int mid=(l+r)>>1;
if(ql<=mid) modify(lc,l,mid,ql,qr,w);
if(qr>mid) modify(rc,mid+1,r,ql,qr,w);
pushup(rt);
}
int query(int rt,int l,int r,int w)
{
if(l==r) return val[rt]>=w?l:l-1;
pushdown(rt);
int mid=(l+r)>>1,res=0;
if(val[lc]>=w) res=query(rc,mid+1,r,w);
else res=query(lc,l,mid,w);
pushup(rt);
return res;
}
void work()
{
n=read();scanf("%lf",&k);
for(reg ll i=1;i<=n;i++) a[i]=read(),b[i]=a[i],siz[i]=1;
sort(b+1,b+n+1);cnt=unique(b+1,b+n+1)-b-1;
for(reg ll i=1;i<=n;i++) a[i]=lower_bound(b+1,b+cnt+1,a[i])-b,t[a[i]]++;
for(reg ll i=cnt-1;i;i--) t[i]+=t[i+1];
for(reg ll i=n;i;i--) fa[i]=floor(i/k),siz[fa[i]]+=siz[i];
build(1,1,cnt);
for(reg ll i=1;i<=n;i++)
{
int ff=floor(i/k);
if(ff&&!vis[ff]) modify(1,1,cnt,1,ans[ff],siz[ff]-1);
vis[ff]=true;
int pos=query(1,1,cnt,siz[i]);
modify(1,1,cnt,1,pos,-siz[i]);
ans[i]=pos;
printf("%lld ",b[pos]);
}
}
}
int main()
{
zzc::work();
return 0;
}