[BZOJ5249][线段树]九省联测:IIIDX

版权声明:虽然博主很菜,但是还是请注明出处(我觉得应该没人偷我的博客) https://blog.csdn.net/qq_43346903/article/details/87926024

BZOJ5249

很容易发现关系可以形成一个树形结构,一个点的子树中的点权都要比它大
则我们给一个点赋值的时候要给它的siz那么多点预留一些点,我们维护f[i]表示i点还可选的点个数,则每次都用线段树维护一下就行了
要容斥一下,如果这个点的father有点权了就要减去这个点的信息

Code:

#include<bits/stdc++.h>
#define ls tr[k].l
#define rs tr[k].r
#define mid ((ls+rs)>>1)
using namespace std;
inline int read(){
	int res=0,f=1;char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
	while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
	return res*f;
}
int n;
double k;
const int N=6e5+5;
int nxt[N],fa[N],siz[N],a[N],ans[N];
namespace segtree{
	struct seg{int l,r,minn,add;}tr[N<<2];
	inline void pushup(int k){tr[k].minn=min(tr[k<<1].minn,tr[k<<1|1].minn);}
	inline void pushadd(int k,int v){tr[k].add+=v;tr[k].minn+=v;}
	inline void pushdown(int k){if(tr[k].add){pushadd(k<<1,tr[k].add);pushadd(k<<1|1,tr[k].add);tr[k].add=0;}}
	void build(int k,int l,int r){
		ls=l,rs=r;tr[k].add=0;
		if(l==r) {tr[k].minn=l;return;}
		build(k<<1,l,mid);build(k<<1|1,mid+1,r);
		pushup(k);
	}
	void update(int k,int ql,int qr,int v){
		if(ls>qr || rs<ql) return;
		if(ql<=ls && rs<=qr) return pushadd(k,v);
		pushdown(k);
		if(qr<=mid) update(k<<1,ql,qr,v);
		else if(ql>mid) update(k<<1|1,ql,qr,v);
		else update(k<<1,ql,mid,v),update(k<<1|1,mid+1,qr,v);
		pushup(k);
	}
	int query(int k,int ql,int qr,int v){
		if(ql==qr) return tr[k].minn>=v?ql:ql+1;
		pushdown(k);int midd=(ql+qr)>>1;
		if(v<=tr[k<<1|1].minn) return query(k<<1,ql,midd,v);
		else return query(k<<1|1,midd+1,qr,v);
	}
}
using namespace segtree;
inline bool cmp(int a,int b){return a>b;}
int main(){
	n=read();scanf("%lf",&k);
	for(int i=1;i<=n;i++) a[i]=read();
	sort(a+1,a+n+1,cmp);
    for(int i=n;i;i--){
        nxt[i]=i,fa[i]=floor(1.*i/k);
        ++siz[i];siz[fa[i]]+=siz[i];
        if(a[i]==a[i+1]) nxt[i]=nxt[i+1];
    }
    build(1,1,n);
    for(int i=1;i<=n;i++){
        if (fa[i] && fa[i]!=fa[i-1]) update(1,ans[fa[i]],n,siz[fa[i]]-1);
		int p=nxt[query(1,1,n,siz[i])];ans[i]=p;
        update(1,p,n,-siz[i]);
    }
    for(int i=1;i<=n;i++) cout<<a[ans[i]]<<" ";
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43346903/article/details/87926024