题意

n个人排成一排,分成两组,第i个人属于a[i]组,每个人有一个能力值b[i],从左往右每个人在第i秒执行一次动作,可以把前面不属于自己组的且能力值小于自己的消灭。
同时有m次操作c[i],可以在第c[i]秒后把所有前面的人包括自己的能力值增加一,求第n秒后的存活人数。

题解

要找出每个人能消灭前面的人数有多少个很难,那么我们考虑第i个人会不会被消灭。做这种题首先要分析清楚随着时间的变化什么是不变的
走两个样例可以看出,如果第j个人在第j秒能消灭第i个人,那么无论第j秒后,他俩的能力值怎么变化,能力值的差值一定是不变的,换句话说,如果第j个人能消灭第i个人,那么在第j秒后,第j个人还是可以消灭第i个人。那么问题就简单了,既然随着时间的增加,结果是不变的,那么我直接跑完n秒后,再去判断有多少人存活也是一样的。处理处第n秒后所有人的能力值,记录从后往前,两个组的最大值,第i个人是否会被消灭,只需判断他的能力值和另一组的最大值的大小即可。
注意:c[i]是可以重复的。

代码

#include <bits/stdc++.h>
using namespace std;
const int maxn = 5e5 + 7, mod = 1e9 + 7;
typedef long long ll;
int n, m, a[maxn], b[maxn], c[maxn];
int main()
{
    int t;
    scanf("%d", &t);
    while (t--) {
        scanf("%d%d", &n, &m);
        memset(c, 0, sizeof(c));
        for (int i = 1; i <= n; i++) scanf("%d%d", &a[i], &b[i]);
        for (int i = 1, x; i <= m; i++) scanf("%d", &x), c[x]++;
        int max1 = 0, max0 = 0, ans = n;
        for (int i = n; i >= 1; i--) c[i] += c[i + 1], b[i] += c[i];
        for (int i = n; i >= 1; i--) {
            if(a[i]) {
                max1 = max(max1, b[i]);
                ans -= (b[i] < max0);
            }
            else {
                max0 = max(max0, b[i]);
                ans -= (b[i] < max1);
            }
        }
        printf("%d\n", ans);
    }
}