题意给出m个bug,每一个bug有个复杂程度,有n个同学每一个同学有自己的能力值b,和想要的东西c,
假设雇佣第i个同学,那么能解决全部复杂程度小于等于b[i]的bug,每天一人仅仅能解决一个,学校要付出c,不论i攻克了几个bug
问,学校在付出不超过s,且最少的天数须要多少。
有两个限制,1.总和不能超过s,2.要求最少天数。
仅仅能限制一个,来求还有一个,假设求总和不能超过s,不好求,那么仅仅能求最少天数,二分枚举最少的天数,找出最小花费,得到最后的结果。
假设雇佣第i个同学,那么能解决全部复杂程度小于等于b[i]的bug,每天一人仅仅能解决一个,学校要付出c,不论i攻克了几个bug
问,学校在付出不超过s,且最少的天数须要多少。
有两个限制,1.总和不能超过s,2.要求最少天数。
仅仅能限制一个,来求还有一个,假设求总和不能超过s,不好求,那么仅仅能求最少天数,二分枚举最少的天数,找出最小花费,得到最后的结果。
假设是时间为t,那么找出全部能力大于当前最大的bug的人,找出须要c最少的,使用优先队列维护,让找出的人工作t天,工作bug最大的t个,使得后面的bug能够找很多其它的人来修。
#include<iostream>
#include<cstdio>
#include<string.h>
#include<algorithm>
#include<ctype.h>
#include<queue>
using namespace std;
__int64 n,m,s;
struct node
{
__int64 a,b,i;
friend bool operator <( node n1, node n2)
{
return n1.b>n2.b;
}
} p[200005],top;
struct w
{
__int64 i,a;
} bug[200005];
int cmp(w x,w y)
{
return x.a>y.a;
}
int cmp1(node x,node y)
{
return x.a>y.a;
}
__int64 PP[110000],last[110000];
int F(__int64 t)
{
priority_queue<node>q;
while( !q.empty() ) q.pop();
__int64 ans=0,i=0,j=0;
while(j<m)
{
while(p[i].a>=bug[j].a&&i<n)
{
q.push(p[i]);
i++;
}
if(q.empty())
return s+1;
top=q.top();
q.pop();
ans+=top.b;
if(ans>s)
return s+1;
__int64 k=j+t;
while(j<m&&j<k)
{
PP[bug[j].i]=top.i;
j++;
}
}
return ans;
}
int main()
{
__int64 i , j ;
memset(last,-1,sizeof(last));
scanf("%I64d %I64d %I64d", &n, &m, &s);
for(i = 0 ; i < m ; i++)
{
scanf("%I64d", &bug[i].a);
bug[i].i = i ;
}
sort(bug,bug+m,cmp);
for(i = 0 ; i < n ; i++)
{
scanf("%I64d", &p[i].a);
p[i].i = i+1 ;
}
for(i = 0 ; i < n ; i++)
{
scanf("%I64d", &p[i].b);
}
sort(p,p+n,cmp1);
__int64 low = 1 , mid , high = m , min1 ;
while( low <= high )
{
mid = (low+high)/2 ;
min1 = F(mid);
if( min1 <= s )
{
for(i = 0 ; i < m ; i++)
last[i] = PP[i] ;
high = mid-1 ;
}
else
low = mid+1 ;
}
if( last[m-1] == -1 )
printf("NO\n");
else
{
printf("YES\n");
for(i = 0 ; i < m ; i++)
{
if(i == m)
printf("%d\n", last[i]);
else
printf("%d ", last[i]);
}
}
return 0;
}