题目大意
给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;
}