CF702F T-Shirts

题面

英文题面

题意:

题解:考虑枚举每个物品,用数据结构来维护人。先将物品按\(v_i\)递减排序,用平衡树来维护人。设当前枚举到了物品\(i\),那么所有平衡树内权值大于等于\(v_i\)的节点的权值都要减去\(v_i\),然后答案\(+1\),但这样会破坏平衡树的二叉搜索树的性质。

考虑权值在\([v_i+1,2v_i]\)的节点会破坏性质,我们就将这些点删除,然后一个一个暴力插回平衡树里。由于这些点的权值都至少减半,每个点只会被这样操作\(log_B\)次。所以复杂度是正确的。

建议使用fhq-treap。注意最后求答案时要将打的标记全部下传。

时间复杂度:\(O(nlogm+mlogmlogB)\)

代码:

#include<bits/stdc++.h>
using namespace std;
#define re register int
#define F(x,y,z) for(re x=y;x<=z;x++)
#define FOR(x,y,z) for(re x=y;x>=z;x--)
typedef long long ll;
#define I inline void
#define IN inline int
#define C(x,y) memset(x,y,sizeof(x))
#define STS system("pause")
template<class D>I read(D &res){
	res=0;register D g=1;register char ch=getchar();
	while(!isdigit(ch)){
		if(ch=='-')g=-1;
		ch=getchar();
	}
	while(isdigit(ch)){
		res=(res<<3)+(res<<1)+(ch^48);
		ch=getchar();
	}
	res*=g;
}
mt19937 _rnd(time(0));
struct P{
	int c,w;
	friend bool operator < (P x,P y){
		return x.w==y.w?x.c<y.c:x.w>y.w;
	}
}p[202000];
int n,m,a[202000],sa[202000],rk[202000],ans[202000];
int root,ch[202000][2],siz[202000],rnd[202000],laz[202000],tag[202000];
inline bool bbb(int x,int y){return a[x]<a[y];}
I push_up(int x){
	siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
}
I build(int &k,int l,int r){
	if(l>r)return;
	k=(l+r)>>1;siz[k]=1;rnd[k]=_rnd();
	build(ch[k][0],l,k-1);build(ch[k][1],k+1,r);
	push_up(k);
}
I add(int k,int val,int num){
	laz[k]+=val;a[k]-=val;ans[k]+=num;tag[k]+=num;
}
I push_down(int x){
	if(ch[x][0])add(ch[x][0],laz[x],tag[x]);
	if(ch[x][1])add(ch[x][1],laz[x],tag[x]);
	laz[x]=tag[x]=0;
}
I split(int now,int k,int &x,int &y){
	if(!now)return x=y=0,void();
	if(laz[now])push_down(now);
	if(a[now]<=k){
		x=now;split(ch[x][1],k,ch[x][1],y);push_up(x);
	}
	else{
		y=now;split(ch[y][0],k,x,ch[y][0]);push_up(y);
	}
}
IN merge(int x,int y){
	if(!x||!y)return x+y;
	if(laz[x])push_down(x);if(laz[y])push_down(y);
	if(rnd[x]<rnd[y]){
		ch[x][1]=merge(ch[x][1],y);push_up(x);return x;
	}
	else{
		ch[y][0]=merge(x,ch[y][0]);push_up(y);return y;
	}
}
I damage(int x){
	if(laz[x])push_down(x);
	if(ch[x][0])damage(ch[x][0]);
	if(ch[x][1])damage(ch[x][1]);
	ch[x][0]=ch[x][1]=0;siz[x]=1;rnd[x]=_rnd();
	re X,Y;split(root,a[x]-1,X,Y);
	root=merge(merge(X,x),Y);
}
I getans(int x){
	if(laz[x])push_down(x);
	if(ch[x][0])getans(ch[x][0]);
	if(ch[x][1])getans(ch[x][1]);
}
int main(){
	read(m);
	F(i,1,m)read(p[i].c),read(p[i].w);sort(p+1,p+1+m);
	read(n);F(i,1,n)read(a[i]),sa[i]=i;
	sort(sa+1,sa+1+n,bbb);F(i,1,n)rk[sa[i]]=i;
	sort(a+1,a+1+n);build(root,1,n);
	re X,Y,Z;
	F(i,1,m){
		split(root,p[i].c-1,X,Y);add(Y,p[i].c,1);split(Y,p[i].c,Y,Z);root=merge(X,Z);
		damage(Y);
	}
	getans(root);
	F(i,1,n)printf("%d ",ans[rk[i]]);
	return 0;
}
/*
3
7 5
3 5
4 3
2
13 14
2
100 500
50 499
4
50 200 150 100
*/
posted @ 2020-07-15 21:12  Purple_wzy  阅读(126)  评论(0编辑  收藏  举报