UVALive 7416 贪心 multiset

UVALive 7416
题目链接:
https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=5158
题意:
给n个人m个敌人。每个人有攻击力和防御力。
要求把所有敌人消灭,在这个前提下我方存活人数最多。
一个人的攻击力大于等于敌人则能把敌人消灭,防御力小于等于敌人攻击力则会被敌人消灭。存在同时存活和同时死亡的情况
一个人只能使用一次。
思路:
算法方面是贪心,实现方面主要是multiset(或者set)的应用
模拟现场赛的思路是对我方人按照攻击力升序,敌方按照防御力升序。对于每一个我方人员有两种思路,一种是杀掉一个未杀掉的敌人,二是替换之前的一个我方人员使得存活人数增加1.然而这样不可避免走向二分匹配的路子上,不是超时就是WA。
实际上,如果按照敌方人员防御力降序排列,每次加入set的都是能杀掉敌人的我方敌人(以攻击力代表我方就行,因为这个时候在set里面的我方士兵都可杀掉当前遍历到的敌方人员)。寻找一个防御力刚好大于地方士兵的我方士兵删除掉,并在存活士兵数加1,否则找到一个防御力最小的士兵删除。存在不合法情况的特判。
源码:

#include <iostream>
#include <iomanip>
#include <sstream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <ctime>
#include <climits>
#include <cassert>
#include <cmath>
#include <string>
#include <bitset>
#include <vector>
#include <deque>
#include <list>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <algorithm>
#include <functional>
#include <utility>
#include <numeric>
#define LL long long
#define gmax(a,b) ((a) > (b) ? (a) : (b))
#define gmin(a,b) ((a) < (b) ? (a) : (b))
#define MOD (1000000007)
using namespace std;
const int MAXN = 100000 + 5;
struct D
{
    int u, v;
}me[MAXN], he[MAXN];
bool cmp1(D a, D b){return a.u > b.u;}
bool cmp2(D a, D b){return a.v > b.v;}
int n, m;
multiset<int>S;
multiset<int>::iterator it;
int main()
{
// freopen("I.in", "r", stdin);
    int t;
    scanf("%d", &t);
    for(int cas = 1 ; cas <= t ; cas++){
        scanf("%d%d", &n, &m);
        for(int i = 0 ; i < n ; i++)
            scanf("%d%d", &me[i].u, &me[i].v);
        for(int i = 0 ; i < m ; i++)
            scanf("%d%d", &he[i].u, &he[i].v);
        printf("Case #%d: ", cas);
        if(n < m){
            printf("-1\n");
            continue;
        }
        S.clear();
        sort(me, me + n, cmp1);
        sort(he, he + m, cmp2);
        int rear = 0;
        int cnt = 0;
        int ok = 1;
        for(int i = 0 ; i < m ; i++){
            while(rear < n && me[rear].u >= he[i].v)
                S.insert(me[rear].v), rear++;
// cout << "begin is " << *S.begin() << endl;
            if(!S.empty()){
                it = S.upper_bound(he[i].u);
                if(it != S.end())
                    S.erase(it), cnt++;
                else
                    S.erase(S.end());
            }
            else{
                ok = 0;
                break;
            }
        }
// printf("Case #%d: ", cas);
        if(ok == 0)
            printf("-1\n");
        else
            printf("%d\n", n - (m - cnt));
    }
    return 0;
}

你可能感兴趣的:(UVALive 7416 贪心 multiset)