分析:
衣服排好序后把所有人插入平衡树,然后用打标记的方式维护买的操作,就是split一下之后把权值都大于当前衣服的那棵树打上购买标记,购买标记分为ans和money两个部分,merge的时候暴力把权值小的树中所有权值大于另外一棵树中某些节点的节点丢到那棵树中,一个节点最多被丢log次所以复杂度是
O
(
n
l
o
g
2
n
)
O(nlog^2n)
O(nlog2n)
Code:
#include<bits/stdc++.h>
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;
}
const int N=200005;
int n,m,root;
int ls[N],rs[N],val[N],key[N],cnt[N],add[N],ans[N];
inline void pushdown(int v){
if(add[v]) {add[ls[v]]+=add[v];add[rs[v]]+=add[v];val[ls[v]]+=add[v];val[rs[v]]+=add[v];add[v]=0;}
if(ans[v]) {ans[ls[v]]+=ans[v];ans[rs[v]]+=ans[v];cnt[ls[v]]+=ans[v];cnt[rs[v]]+=ans[v];ans[v]=0;}
}
void split(int k,int &x,int &y,int v){
if(!k) {x=y=0;return;}
pushdown(k);
if(val[k]<v) x=k,split(rs[k],rs[x],y,v);
else y=k,split(ls[k],x,ls[y],v);
}
int merge(int x,int y){
if(!x || !y) return x+y;
if(key[x]<key[y]){
pushdown(x);
rs[x]=merge(rs[x],y);
return x;
}
else{
pushdown(y);
ls[y]=merge(x,ls[y]);
return y;
}
}
int insert(int x,int y){
int rt1=0,rt2=0;
split(x,rt1,rt2,val[y]);
rt1=merge(rt1,y);
x=merge(rt1,rt2);
return x;
}
int build(int v,int y){
if(!v) return y;
pushdown(v);
y=build(ls[v],y);
y=build(rs[v],y);
ls[v]=rs[v]=0;
return insert(y,v);
}
void dfs(int v){
if(!v)return;
pushdown(v);
dfs(ls[v]);dfs(rs[v]);
}
pair<int,int>a[N];
int main(){
scanf("%d",&n);
for(int i=1,c,q;i<=n;i++){
scanf("%d%d",&c,&q);
a[i]=make_pair(-q,c);
}
sort(a+1,a+1+n);
scanf("%d",&m);
for(int i=1;i<=m;i++){
scanf("%d",&val[i]);
key[i]=rand();
root=insert(root,i);
}
for(int i=1;i<=n;i++){
int c=a[i].second;
int r1=0,r2=0,r3=0,r4=0;
split(root,r1,r2,c);
val[r2]-=c;add[r2]-=c;
cnt[r2]++;ans[r2]++;
split(r2,r3,r4,c-1);
r1=build(r3,r1);
root=merge(r1,r4);
}
dfs(root);
for(int i=1;i<=m;i++) printf("%d ",cnt[i]);
return 0;
}