一眼思路的题…
就是比较难写..
考虑一个点必须小于其
⌊idk⌋
⌊
i
d
k
⌋
那么容易想出一个树形结构,每个点都大于其父亲.
那么对于一个点,那么他能选取的最大值就是当前能选的所有点中的
n−size[id]
n
−
s
i
z
e
[
i
d
]
这个点的值。
然后留够其儿子的位置即可。
最后如果有相同的点,容易想到把当前点放在权值相同的最前面处
c++代码如下:
#include<bits/stdc++.h>
#define lowbit(x) (x & - x)
#define rep(i,x,y) for(register int i = x ; i <= y; ++ i)
#define repd(i,x,y) for(register int i = x ; i >= y; -- i)
using namespace std;
typedef long long ll;
inline char gc(){
static char now[1<<16],*S,*T;
if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;}
return *S++;
}
template<typename T>inline void read(T&x)
{
x = 0;char c;int sign = 1;
do { c = getchar(); if(c == '-') sign = -1; }while(!isdigit(c));
do { x = x * 10 + c - '0'; c = getchar(); }while(isdigit(c));
x *= sign;
}
const int N = 1e6 + 500;
double k; int n,d[N],f[N],size[N];
int head[N],nxt[N << 1],to[N << 1],tot;
inline void add(int x,int y)
{
to[tot] = y;
nxt[tot] = head[x];
head[x] = tot++;
}
struct Seg
{
int lzy[N << 2],lzy2[N << 2],val[N<< 2],mx[N << 2],mi[N << 2];
void build(int id,int l,int r)
{
val[id] = r - l + 1; mx[id] = r;
if(l == r) return;
int mid = l + r >> 1;
build(id<<1,l,mid);
build(id<<1|1,mid+1,r);
}
inline void put_down(int id)
{
if(!lzy[id]) return;
mx[id<<1] += lzy[id];
mx[id<<1|1] += lzy[id];
mi[id<<1] += lzy[id];
mi[id<<1|1] += lzy[id];
lzy[id << 1] += lzy[id];
lzy[id << 1|1] += lzy[id];
lzy[id] = 0;
}
int m;
int Query(int id,int l,int r,int w)
{
if (l == r) return l;
int mid = l + r >> 1;
put_down(id);
int x = val[id<<1|1] - max((max(mx[id<<1],m)- mi[id << 1|1] - mid -1),0);
if(x >= w){
m = max(mx[id<<1],m);
return Query(id<<1|1,mid+1,r,w);
}
else
{
w -= val[id<<1|1];
return Query(id<<1,l,mid,w);
}
}
void update(int id,int l,int r,int L,int R,int w)
{
if(l == L && r == R)
{
mi[id] += w;
mx[id] += w;
lzy[id] += w;
return;
}
int mid = l + r >> 1;
put_down(id);
if(L > mid)update(id<<1|1,mid+1,r,L,R,w);
else if(R <= mid)update(id<<1,l,mid,L,R,w);
else update(id<<1,l,mid,L,mid,w) , update(id<<1|1,mid+1,r,mid+1,R,w);
mx[id] = max(mx[id<<1],mx[id<<1|1]);
mi[id] = max(mi[id<<1],mi[id<<1|1]);
}
void modify(int id,int l,int r,int pos,int w)
{
val[id] += w;
if(l == r) return;
int mid = l + r >> 1;
put_down(id);
if( pos <= mid) modify(id<<1,l,mid,pos,w);
else modify(id<<1|1,mid+1,r,pos,w);
}
}seg;
void dfs(int x)
{
size[x] = 1;
for(register int i = head[x];~i;i=nxt[i])
if(to[i] != f[x])
{
f[to[i]] = x;
dfs(to[i]);
size[x] += size[to[i]];
}
}
int ans[N],p[N],id[N];
int get_fa(int x) { return p[x] == x ? x : p[x] = get_fa(p[x]); }
bool vis[N];
int main()
{
memset(head,-1,sizeof head);
read(n); cin>>k;
rep(i,1,n) read(d[i]);
rep(i,1,n) if((int)(i/k) >= 1) add((int)(i/k),i);
sort(d + 1,d + 1 + n);
rep(i,1,n) p[i] = i;
rep(i,1,n) if(d[i] != d[i-1]) id[i] = i;else id[i] = id[i-1];
seg.build(1,1,n);
rep(i,1,n) if(!size[i]) dfs(i);
rep(x,1,n)
{
if(f[x]) seg.update(1,1,n,1,ans[f[x]],-size[f[x]]);
if(f[x]) seg.modify(1,1,n,ans[f[x]],size[f[x]]);
seg.m = 0;
ans[x] = seg.Query(1,1,n,size[x]);
ans[x] = id[ans[x]];
ans[x] = get_fa(id[ans[x]]);
p[ans[x]] = ans[x] + 1;
if(f[x]) size[f[x]] -= size[x];
if(f[x]) seg.update(1,1,n,1,ans[f[x]],size[f[x]]);
if(f[x]) seg.modify(1,1,n,ans[f[x]],-size[f[x]]);
seg.update(1,1,n,1,ans[x],size[x]);
seg.modify(1,1,n,ans[x],-size[x]);
}
rep(i,1,n) printf("%d ",d[ans[i]]);
return 0;
}