题目来源:
https://codeforces.com/contest/1257/problem/D
题目描述:
题意:
有
个怪兽 ,每个怪兽都有能力值
。
然后现在你有
个英雄,每个英雄也有能力值
,每个英雄还有一个
,表示这个英雄一天最多能消灭多少个怪兽,现在你必须一个接一个的消灭怪兽,不能改变顺序,然后问你最少多少天,能够消灭所有的怪兽。
思路:
PS:看群友O(n)的神仙贪心,学不来学不来。
二分+RMQ(维护区间最值),pre数组预处理:杀到当前体力的最大攻击力,然后二分
,
。
PS:用
优化
查询为
参考代码:
/* 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;
}