题意:
有
n
n
n种 T 恤,每种有价格
c
i
c_i
ci 和品质
q
i
q_i
qi。
有
m
m
m 个人要买 T 恤,第
i
i
i 个人有
v
i
v_i
vi 元,每人每次都会买一件能买得起的
q
i
q_i
qi 最大的 T 恤。一个人只能买一种 T 恤一件,所有人之间都是独立的。
问最后每个人买了多少件 T 恤?如果有多个
q
i
q_i
qi 最大的 T 恤,会从价格低的开始买。
题解:
对所有衣服按照
q
[
i
]
q[i]
q[i]从大到小排序
对每个人维护
a
[
i
]
a[i]
a[i]表示其剩余的钱,
b
[
i
]
b[i]
b[i]表示其买的衣服数量
对所有人按照
a
[
i
]
a[i]
a[i]从小到大排序,初始
b
[
i
]
=
0
b[i]=0
b[i]=0
之后枚举每件衣服
j
=
1
−
>
n
j=1->n
j=1−>n
衣服j对人的影响就是把全局
a
[
i
]
>
=
q
[
j
]
a[i]>=q[j]
a[i]>=q[j]的人都
a
[
i
]
−
=
q
[
j
]
a[i]-=q[j]
a[i]−=q[j],并且
b
[
i
]
+
+
b[i]++
b[i]++
用一棵平衡树维护每个人,按
a
a
a从小到大排列
每次找出所有
a
[
i
]
>
=
p
[
j
]
a[i]>=p[j]
a[i]>=p[j]的人,将其
a
[
i
]
−
=
p
[
j
]
a[i]-=p[j]
a[i]−=p[j],并且
b
[
i
]
+
+
b[i]++
b[i]++
这里我们考虑令
x
=
p
[
j
]
x=p[j]
x=p[j],所有在
[
0
,
x
)
[0,x)
[0,x)内的数不动,把所有在
[
x
,
2
x
]
[x,2x]
[x,2x]内的数暴力修改,之后将
>
2
x
>2x
>2x的数直接打一个b加,a减的标记
可以发现 [ x , 2 x ] [x,2x] [x,2x]内的元素至少减半了,所以这样的暴力操作对每个点最多进行 O ( l o g v ) O(logv) O(logv)次
找了一天bug,头晕加眼花
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
mt19937 rnd(233);
struct FHQ{
int cnt,root;
int ls[maxn],rs[maxn],val[maxn],key[maxn],siz[maxn];
int sum[maxn],lazy[maxn],sub[maxn];
int newnode(int x){
val[++cnt]=x;
key[cnt]=rnd();
siz[cnt]=1;
return cnt;
}
// void update(int node){
// siz[node]=siz[ls[node]]+siz[rs[node]]+1;
// }
void push_down(int node){
if(lazy[node]){
if(ls[node]) lazy[ls[node]]+=lazy[node],sum[ls[node]]+=lazy[node];
if(rs[node]) lazy[rs[node]]+=lazy[node],sum[rs[node]]+=lazy[node];
lazy[node]=0;
}
if(sub[node]){
if(ls[node]) val[ls[node]]-=sub[node],sub[ls[node]]+=sub[node];
if(rs[node]) val[rs[node]]-=sub[node],sub[rs[node]]+=sub[node];
sub[node]=0;
}
}
void split_val(int node,int vals,int &x,int &y){
if(!node){
x=y=0;
return ;
}
push_down(node);
if(val[node]<=vals){
x=node;
split_val(rs[node],vals,rs[node],y);
}
else{
y=node;
split_val(ls[node],vals,x,ls[node]);
}
//update(node);
}
int mer(int x,int y){ //大顶堆
if(!x||!y) return x+y;
if(key[x]>key[y]){
push_down(x);
rs[x]=mer(rs[x],y);
//update(x);
return x;
}
else{
push_down(y);
ls[y]=mer(x,ls[y]);
//update(y);
return y;
}
}
void ins(int vals){
int x=0,y=0;
split_val(root,vals,x,y);
root=mer(mer(x,newnode(vals)),y);
}
int x,y,z;
void sol(int pric){
x=0,y=0,z=0;
split_val(root,pric-1,x,y);
lazy[y]++;
sub[y]+=pric;
sum[y]++;
val[y]-=pric;
split_val(y,pric-1,y,z);
dfs(y);
root=mer(x,z);
}
void dfs(int node){
if(!node) return;
push_down(node);
dfs(ls[node]);
dfs(rs[node]);
int xx=0,yy=0;
ls[node]=rs[node]=0;
split_val(x,val[node],xx,yy);
x=mer(mer(xx,node),yy);
}
void print(int node){
if(!node) return ;
push_down(node);
print(ls[node]);
print(rs[node]);
}
}fhq;
struct Case{
int c,q;
bool operator < (const Case & a)const{
if(q!=a.q) return q>a.q;
else return c<a.c;
}
}a[maxn];
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i].c>>a[i].q;
}
sort(a+1,a+1+n);
int q;
cin>>q;
for(int i=1;i<=q;i++){
int x;
cin>>x;
fhq.ins(x);
}
for(int i=1;i<=n;i++){
fhq.sol(a[i].c);
}
fhq.print(fhq.root);
for(int i=1;i<=q;i++){
cout<<fhq.sum[i]<<" ";
}
}