bzoj 5249: [2018多省省队联测]IIIDX 线段树维护贪心

题目:点击打开链接

题解:点击打开链接

关键:处理相同的数。给每个子树预留位置,再按点标号一次处理。

        每次贪心尽量选最大,在线段树上二分

注意:先离散化,且不用去重(重复的数不影响,区间减的时候都会减掉)

            1-n的顺序从小到大,而不是从大到小

#include<bits/stdc++.h>
using namespace std;
#define maxn 500020
#define ls(x) (x << 1)
#define rs(x) ((x << 1) ^ 1)
#define mid(l,r) ((l + r) >> 1)

struct node{
	int next,to;
}e[maxn * 2];
int head[maxn],cnt,vis[maxn],fa[maxn],id[maxn],sz[maxn];
int a[maxn],b[maxn],n,tot;
int num[maxn],add[maxn << 2],mn[maxn << 2];
double k;

inline void adde(int x,int y){
	e[++cnt].to = y;
	e[cnt].next = head[x];
	head[x] = cnt;
}
inline void update(int x){
	mn[x] = min(mn[ls(x)],mn[rs(x)]);
}
void build(int x,int l,int r){
	if ( l == r ){ mn[x] = num[l]; return; }
	build(ls(x),l,mid(l,r));
	build(rs(x),mid(l,r) + 1,r);
	update(x);
}

void init(){
	for (int i = n ; i >= 1 ; i--){
		int x = floor((double)i / k);
		sz[i]++;
		if ( x ) fa[i] = x , adde(x,i) , sz[x] += sz[i];
	}
	sort(b + 1,b + n + 1);
	for (int i = 1 ; i <= n ; i++) a[i] = lower_bound(b + 1,b + n + 1,a[i]) - b , num[a[i]]++;
	for (int i = n ; i >= 1 ; i--) num[i] += num[i + 1];
	build(1,1,n);
}
inline void Add(int x,int d){
	add[x] += d , mn[x] += d;
}
inline void pushdown(int x){
	if ( add[x] ){
		Add(ls(x),add[x]) , Add(rs(x),add[x]);
		add[x] = 0;
	}
}
void modify(int x,int l,int r,int ls,int rs,int d){
	if ( ls <= l && rs >= r ){ Add(x,d); return; }
	pushdown(x);
	register int mid = (l + r) >> 1;
	if ( ls <= mid ) modify(ls(x),l,mid,ls,rs,d);
	if ( rs > mid ) modify(rs(x),mid + 1,r,ls,rs,d);
	update(x);
}
int query(int x,int l,int r,int sz){
	if ( l == r ) return mn[x] >= sz ? l : l - 1;
	pushdown(x);
	if ( sz <= mn[ls(x)] ) return query(rs(x),mid(l,r) + 1,r,sz);
	return query(ls(x),l,mid(l,r),sz);
}
int main(){
	freopen("input.txt","r",stdin);
	scanf("%d %lf",&n,&k);
	for (int i = 1 ; i <= n ; i++) scanf("%d",&a[i]) , b[i] = a[i];
	init();
	for (int i = 1 ; i <= n ; i++){
		if ( fa[i] ) modify(1,1,n,1,id[fa[i]],sz[i]);
		id[i] = query(1,1,n,sz[i]);
		modify(1,1,n,1,id[i],-sz[i]);
	}
	for (int i = 1 ; i <= n ; i++) printf("%d ",b[id[i]]);
	printf("\n");
	return 0;
}


猜你喜欢

转载自blog.csdn.net/weixin_42484877/article/details/80921544