1. 程式人生 > >HDU 4864 Task (2014多校聯合訓練第一場1004) 解題報告(貪心)

HDU 4864 Task (2014多校聯合訓練第一場1004) 解題報告(貪心)

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);
    }
}