HDU 4864 Task (2014多校联合训练第一场1004) 解题报告(贪心)

56 篇文章 0 订阅

Task

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 400    Accepted Submission(s): 72


Problem Description
Today the company has m tasks to complete. The ith task need xi minutes to complete. Meanwhile, this task has a difficulty level yi. The machine whose level below this task’s level yi cannot complete this task. If the company completes this task, they will get (500*xi+2*yi) dollars.
The company has n machines. Each machine has a maximum working time and a level. If the time for the task is more than the maximum working time of the machine, the machine can not complete this task. Each machine can only complete a task one day. Each task can only be completed by one machine.
The company hopes to maximize the number of the tasks which they can complete today. If there are multiple solutions, they hopes to make the money maximum.
 

Input
The input contains several test cases. 
The first line contains two integers N and M. N is the number of the machines.M is the number of tasks(1 < =N <= 100000,1<=M<=100000).
The following N lines each contains two integers xi(0<xi<1440),yi(0=<yi<=100).xi is the maximum time the machine can work.yi is the level of the machine.
The following M lines each contains two integers xi(0<xi<1440),yi(0=<yi<=100).xi is the time we need to complete the task.yi is the level of the task.
 

Output
For each test case, output two integers, the maximum number of the tasks which the company can complete today and the money they will get.
 

Sample Input
  
  
1 2 100 3 100 2 100 1
 

Sample Output
  
  
1 50004
 

Source
 

    首先,我们可以确定这是一道贪心的题目。整个贪心的思路比赛时和队友也讨论了很久,最终确定了一个没有漏洞的:
    将机器按照先等级,后时间的顺序排序,按顺序枚举机器。在枚举等级为yi的机器时,找到等级为0 到 yi的、时间最大且能被机器完成、等级尽量高的任务。
    因为价值函数是500 * x + 2 * y, y的范围是0-100,所以时间越长必然是价值越大。
    使用线段树维护等级为0到当前等级的所有任务,每次查找时间符合条件的最大值即可。因为同时要找等级较高的,所以将时间和等级按照 x*102-101+y 结合起来,查找时找区间0 到 x*102的最大值即可。
    代码如下:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <string>
using namespace std;

#define ff(i, n) for(int i=0;i<(n);i++)
#define fff(i, n, m) for(int i=(n);i<=(m);i++)
#define dff(i, n, m) for(int i=(n);i>=(m);i--)
typedef long long LL;
typedef unsigned long long ULL;
void work();

int main()
{
#ifdef ACM
    freopen("in.txt", "r", stdin);
#endif // ACM

    work();
}

/***************************************************/

#define lson l, m, pos<<1
#define rson m+1, r, pos<<1|1
#define hehe 1, 200000, 1

const int maxn = 200000;
int ma[maxn<<2], num[maxn<<2];

void updateFather(int pos)
{
    ma[pos] = max(ma[pos<<1], ma[pos<<1|1]);
}

void update(int p, int v, int l, int r, int pos)
{
    if(l == r)
    {
        num[pos] += v;

        if(num[pos])
            ma[pos] = l;
        else
            ma[pos] = 0;

        return;
    }

    int m = (l+r)/2;
    if(p <= m)
        update(p, v, lson);
    else
        update(p, v, rson);

    updateFather(pos);
}

int query(int L, int R, int l, int r, int pos)
{
    if(L<=l && r<=R)
        return ma[pos];

    int m = (l+r)/2;
    return max(L<=m?query(L, R, lson):0, m<R?query(L, R, rson):0);
}

int cal(int x, int y)
{
    return x*102-101+y;
}

void work()
{
    int n, m;
    while(~scanf("%d%d", &n, &m))
    {
        vector<int> machine[101];
        vector<int> task[101];

        int x, y;

        ff(i, n)
            scanf("%d%d", &x, &y), machine[y].push_back(x);
        ff(i, m)
            scanf("%d%d", &x, &y), task[y].push_back(x);

        ff(i, 101)
            sort(machine[i].begin(), machine[i].end());

        memset(num, 0, sizeof(num));
        memset(ma, 0, sizeof(ma));

        int ans = 0;
        LL money = 0;
        ff(i, 101)
        {
            ff(j, task[i].size())
                update(cal(task[i][j], i), 1, hehe);

            ff(j, machine[i].size())
            {
                int x = machine[i][j];
                int q = query(1, cal(x, 101), hehe);
                if(q > 0)
                {
                    update(q, -1, hehe);
                    ans++;

                    int xx = q/102+1;
                    int yy = q%102-1;
                    money += xx*500 + 2*yy;
                }
            }
        }

        printf("%d %I64d\n", ans, money);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值