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
*/