## 思路:
### 单调性:
显然的,当 $k$ 越大,吃完菜的可能是越大的。
### 贪心:
将题目拆解成子问题。
根据题意归纳可得,你一定需要让挑剔的人在保证美味度的情况下,尽可能的吃贵的菜,让贫穷的人在保证价格的情况下尽可能吃美味度小的菜(其实随便吃就行,不影响),可以用优先队列进行维护。
将挑剔的人从大到小排序后,可以保证上一个人可以吃的菜,这一个人也一定能吃,然后尽可能吃 $k$ 周贵的。
将贫穷的人从小到大排序后,可以保证上一个人可以吃的菜,这一个人也一定能吃,然后尽可能吃 $k$ 周美味度小的的。
### 时间复杂度:
$\mathcal{O(n\log^2{n})}$。
## code:
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MAXM=200005,MAXN=50005;
int n,l1,l2,m,b[MAXN],c[MAXN];
struct node{
int w,v;
bool operator <(const node &x)const{
return v<x.v;
}
}a[MAXN<<2],sf[MAXN<<2];
priority_queue <node> q;
bool cmp(node a,node b){
return a.w>b.w;
}
bool check(int k){
if((n-l1-l2)*k>=m){
return 1;
}
while(!q.empty()){
q.pop();
}
int tot=1;
for(int i=1;i<=l1;i++){
while(tot<=m && a[tot].w>=b[i]){
q.push(a[tot++]);
}
for(int j=1;j<=k && !q.empty();j++){
q.pop();
}
}
int cnt=0;
while(!q.empty()){
sf[++cnt]=q.top();
q.pop();
}
for(int i=tot;i<=m;i++){
sf[++cnt]=a[i];
}
sort(sf+1,sf+cnt+1);
tot=1;
for(int i=1;i<=l2;i++){
while(tot<=m && sf[tot].v<=c[i]){
q.push(sf[tot++]);
}
for(int j=1;j<=k && !q.empty();j++){
q.pop();
}
}
int r=q.size()+cnt-tot+1;
return r<=(n-l1-l2)*k;
}
signed main(){
cin>>n>>m>>l1>>l2;
for(int i=1;i<=m;i++){
cin>>a[i].w>>a[i].v;
}
sort(a+1,a+m+1,cmp);
for(int i=1;i<=l1;i++){
cin>>b[i];
}
sort(b+1,b+l1+1);
reverse(b+1,b+l1+1);
for(int i=1;i<=l2;i++){
cin>>c[i];
}
sort(c+1,c+l2+1);
int l=1,r=m,ans=-1;
while(l<=r){
int mid=(l+r)>>1;
if(check(mid)){
ans=mid;
r=mid-1;
}else{
l=mid+1;
}
}
cout<<ans;
return 0;
}
488

被折叠的 条评论
为什么被折叠?



