Educational Codeforces Round 76 (Rated for Div. 2) D. Yet Another Monster Killing Problem(二分+RMQ)

题目来源:

https://codeforces.com/contest/1257/problem/D

题目描述:

在这里插入图片描述

题意:

n n 个怪兽 ,每个怪兽都有能力值 a i a_i
然后现在你有 m m 个英雄,每个英雄也有能力值 p i p_i ,每个英雄还有一个 s i s_i ,表示这个英雄一天最多能消灭多少个怪兽,现在你必须一个接一个的消灭怪兽,不能改变顺序,然后问你最少多少天,能够消灭所有的怪兽。

思路:

PS:看群友O(n)的神仙贪心,学不来学不来。
二分+RMQ(维护区间最值),pre数组预处理:杀到当前体力的最大攻击力,然后二分 m i d mid c h e c k check即可
PS:用 S T ST 优化 R M Q RMQ 查询为 O ( 1 ) O(1)

参考代码:

/* CF was purple years ago!
 * Thanks cf-tool!
 * Author: nuoyanli
 * Time: 2019-11-13 22:35:09
 **/

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define lson l, mid, root << 1
#define rson mid + 1, r, root << 1 | 1
#define min(a, b) a > b ? b : a
#define max(a, b) a < b ? b : a
#define ll long long
using namespace std;
const int N = 2e5 + 10;
const int M = 25;
struct node {
  ll x, y;
  bool operator<(const node &_a) const { return y < _a.y; }
} ans[N];
int a[N], Log[N], f[N][M], pre[N], n, m;
void GetLog() {
  int i;
  Log[1] = 0;
  for (i = 2; i <= n + 1; ++i)
    Log[i] = Log[i / 2] + 1;
}
void RMQ() {
  int i, j;
  for (i = 1; i <= n; ++i)
    f[i][0] = a[i];
  for (j = 1; (1 << j) <= n; ++j)
    for (i = 1; i + (1 << (j - 1)) <= n; ++i)
      f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
}

signed main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int t;
  cin >> t;
  while (t--) {
    cin >> n;
    for (int i = 1; i <= n; i++) {
      cin >> a[i];
    }
    cin >> m;
    for (int i = 1; i <= m; i++) {
      cin >> ans[i].x >> ans[i].y;
    }
    sort(ans + 1, ans + 1 + m);
    pre[n + 1] = 0;
    for (int i = n, j = m; i; --i) {
      pre[i] = pre[i + 1];
      while (j && ans[j].y == i) {
        pre[i] = max(pre[i], ans[j].x);
        --j;
      }
    }
    GetLog();
    RMQ();
    int sum = 0, now = 1;
    while (now <= n) {
      int l = 0, r = n - now + 1, mid, la;
      while (l <= r) {
        mid = l + r >> 1;
        int k, a;
        k = Log[now + mid - 1 - now + 1];
        a = max(f[now][k], f[now + mid - 1 - (1 << k) + 1][k]);
        if (!mid || pre[mid] >= a)
          la = mid, l = mid + 1;
        else
          r = mid - 1;
      }
      if (la == 0) {
        sum = -1;
        break;
      }
      ++sum;
      now += la;
    }
    cout << sum << endl;
  }
  return 0;
}
发布了293 篇原创文章 · 获赞 212 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/nuoyanli/article/details/103083870