CodeForces - 702F
分析
发现统计单个人买T恤是十分困难的,考虑用T恤去贡献单个人。
将T恤按照 \(q_i\) 排序,买T恤这一操作变成将 \([c_i,end]\)这段数量加一并平移。发现 \([c_i,2c_i)\) 这一部分不好处理,我们不妨暴力插入,这样每个人只会被暴力插入 \(logc_i\) 次,那么总复杂度即为 \(O(nlognlogV)\),可以通过此题。
代码
实现较为容易
const int N=2e5+10;
int n,k,root,tot;
struct node{
int ls,rs,key,val,sz;
int cnt,tagcnt,tagval,id;
}t[N];
void pushdown(int id){
if(t[id].tagcnt){
if(t[id].ls) t[t[id].ls].cnt+=t[id].tagcnt,t[t[id].ls].tagcnt+=t[id].tagcnt;
if(t[id].rs) t[t[id].rs].cnt+=t[id].tagcnt,t[t[id].rs].tagcnt+=t[id].tagcnt;
t[id].tagcnt=0;
}
if(t[id].val){
if(t[id].ls) t[t[id].ls].val+=t[id].tagval,t[t[id].ls].tagval+=t[id].tagval;
if(t[id].rs) t[t[id].rs].val+=t[id].tagval,t[t[id].rs].tagval+=t[id].tagval;
t[id].tagval=0;
}
}
int merge(int x,int y){
if(!x||!y) return x^y;
pushdown(x),pushdown(y);
if(t[x].key>t[y].key)
return t[x].rs=merge(t[x].rs,y),x;
else
return t[y].ls=merge(x,t[y].ls),y;
}
void split(int now,int val,int &x,int &y){
if(!now)
return x=y=0,void();
pushdown(now);
if(t[now].val<=val) x=now,split(t[now].rs,val,t[x].rs,y);
else y=now,split(t[now].ls,val,x,t[y].ls);
}
int x,y,z,ans[N];
int new_node(int val,int i){
t[++tot]={0,0,rand(),val,1,0,0,0,i};
return tot;
}
void insert(int val,int i){
split(root,val,x,y);
root=merge(merge(x,new_node(val,i)),y);
}
PII a[N];
void dfs(int u,int &x,int v){
if(!u) return ;
dfs(t[u].ls,x,v),dfs(t[u].rs,x,v);
int k1,k2;t[u].val-=v,t[u].ls=t[u].rs=0,t[u].cnt++;
split(x,t[u].val,k1,k2);
x=merge(merge(k1,u),k2);
}
void calc(int u){
if(!u) return ;
pushdown(u);
calc(t[u].ls),calc(t[u].rs);
ans[t[u].id]=t[u].cnt;
}
void Main(){
n=rd;
for(int i=1;i<=n;i++) a[i]={rd,rd},swap(a[i].fi,a[i].se);
sort(a+1,a+n+1);
k=rd;
for(int i=1,x;i<=k;i++)
x=rd,insert(x,i);
for(int i=1;i<=n;i++){
int c=a[i].second;
split(root,c-1,x,y);split(y,c<<1,y,z);
if(z){t[z].val-=c,t[z].cnt++;t[z].tagcnt++,t[z].tagval-=c;}
dfs(y,x,c);root=merge(x,z);
}
calc(root);
for(int i=1;i<=k;i++)
printf("%d ",ans[i]);
}