题意:
给出n个人的能力值,m个问题的难度值,请n个人需要的花费,花钱的上限s
每个人能解决难度值小于等于他能力值的问题
求出能否在花钱不超过s的情况下把所有问题解决
如果可以输出YES
并输出每个问题由谁来解决的最快的方案
如果不行输出NO
分析:
可以二分枚举天数,因为如果一个任务能x天完成,肯定也能在大于x的天数内完成
如果现在我们是要x天内完成
可以先把任务按复杂程度排序,把人也按复杂度排序
然后对每个任务,找出所有能解决这个问题的人并且把他们压入优先队列(费用低的权大),然后弹出队列里费用最低的, 让这个人解决尽可能多的问题(不超过x个或者就是x个),然后找出紧接着的没有被这个人或前面的人解决的问题,重复上述步骤,继续把能解决它的人压入队列(不要重复压已经压过的),然后弹出队里费用最低的。
如果最后优先队列为空而问题还在,则说明人手不够,不能在x天内完成
否则如果总花费超过s,也是不能在x天内完成
否则可以在x天内完成
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
#define pb push_back
const long long NN=111111;
long long n,m,ss;
long long ans[NN];
struct P{
long long b,c,id;
bool operator< (const P another)const{
return (this->c)>another.c;
}
}p[NN],a[NN];
bool cmp(P s1,P s2){
return s1.b<s2.b;
}
priority_queue<P> que;
bool check(long long s){
memset(ans,0,sizeof(ans));
while(!que.empty()) que.pop();
long long qi;
long long pi=n;
long long all=0;
for(qi=m;qi>=1;){
for(pi=pi;pi>=1;pi--){
if(p[pi].b>=a[qi].b) que.push(p[pi]);
else break;
}
if(que.empty()) return false;
P ps=que.top();que.pop();
all+=ps.c;
long long cnt=0;
for(qi=qi;qi>=1;qi--){
if(ps.b>=a[qi].b){
cnt++;
ans[a[qi].id]=ps.id;
}
else break;
if(cnt==s){
qi--;break;
}
}
//if(qi>=1 && pi==0) return false;
if(qi==0 && all>ss) return false;
if(qi==0 && all<=ss) return true;
}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("G:/in.txt","r",stdin);
//freopen("G:/myout.txt","w",stdout);
#endif
cin>>n>>m>>ss;
for(long long i=1;i<=m;i++) cin>>a[i].b,a[i].id=i;
for(long long i=1;i<=n;i++) cin>>p[i].b;
for(long long i=1;i<=n;i++) cin>>p[i].c,p[i].id=i;
sort(a+1,a+1+m,cmp);
sort(p+1,p+1+n,cmp);
long long l=1,r=m,mid=(l+r)/2;
while(l<r){
if(check(mid)) r=mid;
else l=mid+1;
mid=(l+r)/2;
}
if(check(mid)){
cout<<"YES"<<endl;
for(long long i=1;i<=m;i++)
cout<<ans[i]<<' ';
cout<<endl;
}else{
cout<<"NO"<<endl;
}
}