Codeforces 1257D Yet Another Monster Killing Problem(二分+贪心)

题目链接

题目大意

  给n个数a,之后再给m组数b,b中每组数第一个数如果大于a中的某个数,则可以删除这个数,第二个数代表这个数一次能删除几个连续的数。a中的每个数只能按顺序被删除,问最小删除次数。

解题思路

  首先先把b中的数按第一个数排序,然后用一个数组记录大于等于这个数的最大次数,如果次数用完了或者出现了更大的数,就二分找一个更大的数,然后更新次数,依次贪心即可。

代码

const int maxn = 2e5+10;
const int maxm = 2e2+10;
struct IF {
    int x, cnt;
} info[maxn], arr[maxn]; int post[maxn];
int main() {
    int t; cin >> t;
    while(t--) {
        int n; cin >> n;
        for (int i = 1; i<=n; ++i) scanf("%d", &arr[i].x); 
        int m; cin >> m;
        for (int i = 1; i<=m; ++i) scanf("%d%d", &info[i].x, &info[i].cnt);
        sort(info+1, info+m+1, [](IF a, IF b) {return a.x<b.x;});
        post[m+1] = 0;
        for (int i = m; i>=1; --i) post[i] = max(post[i+1], info[i].cnt);
        int damage = 0, cnt = 0, days = 0, ans = 0;
        for (int i = 1; i<=n; ++i) {
            ++cnt;
            if (days<cnt || damage<arr[i].x) {
                int p = lower_bound(info+1, info+m+1, arr[i], [](const IF &a, const IF &b) {return a.x<b.x;})-info;
                if (p==m+1) {
                    cout << -1 << endl; goto out;
                }
                if (days<cnt) ++ans, cnt = 1;
                days = post[p], damage = info[p].x;
                if (days<cnt) ++ans, cnt = 1;
            }
        }
        cout << ans << endl;
        out:;
    }
    return 0;   
}
posted @ 2020-08-31 15:24  shuitiangong  阅读(149)  评论(0编辑  收藏  举报