真正的AC自动机(二分 + 优先队列)

来源:互联网 发布:中情局十条诫令 知乎 编辑:程序博客网 时间:2024/06/08 16:34

Problem Description

自从小Z学了字符串的AC自动机,便觉得非常失望,说好的能够帮我自动AC题目的机器呢?5555555555…….
小Z希望自己发明一个真正的,能够自动AC题目的机器。
他的实现很简单,去ACdream王国请N个ACMers帮他切题目,哇咔咔~真是机智啊!!!
每个ACMer都有自己的能力,只有当题目的难度不超过他的能力,他才能够做出来。
然而由于精力有限,每个ACMer每天最多只能做一道题。
当然啦,ACMers不可能义务为小Z劳动,因此每个ACMers被雇佣之后,小Z都要给他一笔“出场费“,无论是做出多少道题。
好了,老师布置给小Z M道题目,每一道题目的难度都知道了。而小Z手上只有L元。
请问小Z是否能用他的AC自动机尽可能快地完成老师布置给他的作业呢?
Input

多组数据,每组数据首先是三个整数N,M,L,表示小Z能请到的ACMers的数目以及老师布置给小Z的题目数,还有小Z手上有的财富。
接下来是N个整数a[i],表示第i位ACMers的能力值。
接下来是N个整数c[i],表示第i位ACMers的出场费。
接下来是M个整数d[i],表示第i道题目的难度。

Output

对于每组数据,如果小Z不能完成作业,那么请输出”Do it yourself“(不包括双引号,注意大小写)。
若小Z能完成作业,请先输出”Good Luck“,然后输出M个整数ans[i],表示第i道题由第ans[i]名ACMer完成。
答案不唯一,输出一组合法解即可。
Sample Input

3 4 9
2 1 3
4 3 6
1 3 1 2
3 4 5
2 1 3
5 3 6
1 3 1 2
Sample Output

Good Luck
2 3 2 3
Do it yourself
Hint

对于第一个情况,只需要请第2,3名程序猿即可。对于第二个情况由于大家的身价都比较高,因此大家都不愿因自降身价,所以小Z只好自己做了。

在财力有限下,最快做完题目的时间。
跟之前做的一个自行车题目很像,首先一个策略可以想到就是能搞这个题目的人中,最便宜的那个是最好的。如果把题目难度从高到低排列,那么之前选出来的人可以继续用来写难度较低的题目(因为每个题目只有一个人写)。
对于天数,就用二分来解决,看这些天内是否能解决。

#include<cstdio>#include<cstring>#include<iostream>#include<queue>#include<vector>#include<algorithm>#include<string>#include<cmath>#include<set>#include<map>#include<vector>using namespace std;typedef long long ll;const int inf = 0x3f3f3f3f;const int maxn = 100005;struct Node{    int id,val,money;}node[100005];struct Pro{    int id,dif;}pro[100005];int ans[100005],m,l,n;bool cmp1(Node a,Node b){    if(a.val == b.val)return a.money < b.money;    return a.val > b.val;}bool cmp2(Pro a,Pro b){    return a.dif > b.dif;}struct cmp{    bool operator()(Node a,Node b)    {        return a.money > b.money;    }};bool check(int x){    priority_queue<Node,vector<Node>,cmp>pq;    int cost = 0;    for(int i = 1,j = 1;i <= m;)    {        while(j <= n&&pro[i].dif <= node[j].val)        {            pq.push(node[j]);j++;        }        if(!pq.size())return false;        cost += pq.top().money;        if(cost > l)return false;        int temp = ans[pro[i].id] = pq.top().id;        pq.pop();        for(int k = 2;k <= x;k++)        {            i++;            if(i > m)return true;            ans[pro[i].id] = temp;        }    }    return true;}int main(){    #ifdef LOCAL    freopen("C:\\Users\\ΡΡ\\Desktop\\in.txt","r",stdin);    //freopen("C:\\Users\\ΡΡ\\Desktop\\out.txt","w",stdout);    #endif // LOCAL    while(scanf("%d%d%d",&n,&m,&l) != EOF)    {        for(int i = 1;i <= n;i++)        {            scanf("%d",&node[i].val);            node[i].id = i;        }        for(int i = 1;i <= n;i++)            scanf("%d",&node[i].money);        for(int i = 1;i <= m;i++)        {            pro[i].id = i;            scanf("%d",&pro[i].dif);        }        sort(node + 1,node + 1 + n,cmp1);        sort(pro + 1,pro + 1 + m,cmp2);        int l = 0,flag = 0;        int r = 100000;        while(l < r)        {            int mid = (l + r)/2;            if(check(mid))            {                r = mid - 1;flag = 1;            }            else l = mid + 1;        }        if(flag)        {            printf("Good Luck\n");            printf("%d",ans[1]);            for(int i = 2;i <= m;i++)                printf(" %d",ans[i]);            printf("\n");        }        else printf("Do it yourself\n");    }    return 0;}
0 0
原创粉丝点击