题目大意

存在图片说明 个人,每个人分配在0,1两个阵营之中,还有对应自己的能力值
存在图片说明 次操作,每次输入图片说明图片说明 能力值+1。

解决方法

如果从前往后统计,对于每个人,需要在图片说明 秒之后才可以被增幅,要考虑的因素比较多。
换个思路,我们知道每图片说明 个人在他行动阶段只会对前图片说明 个人产生影响。后面的人是不存在影响的,所以如果后面存在能力值比第图片说明 个人能力值高的,第图片说明 个人就会牺牲。
这样我们先考虑全部玩家先增幅完毕,计算到能力值的最大值。从后往前遍历,因为这样的话如果这个人小于另一队当前的最大值,并且这个是被增幅之后的,仍小于最大值,说明这个人就将被另一队最大值淘汰。

时间复杂度O(N)

https://ac.nowcoder.com/acm/contest/view-submission?submissionId=43529623&returnHomeType=1&uid=919749006

Code

#include <bits/stdc++.h>
using namespace std;
#define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
typedef long long ll;

inline int read() {
    int s = 0, w = 1; char ch = getchar();
    while (ch < 48 || ch > 57) { if (ch == '-') w = -1; ch = getchar(); }
    while (ch >= 48 && ch <= 57) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();
    return s * w;
}

const int N = 5e4 + 7;
struct Node {
    int x;
    int y;
}a[N];
int b[N];

int main() {
    int T = read();
    while (T--) {
        memset(b, 0, sizeof(b));
        int n = read(), m = read();
        for (int i = 1; i <= n; ++i)
            a[i].x = read(), a[i].y = read();
        for (int i = 1; i <= m; ++i) {
            int k = read();
            ++b[k];
        }
        // 后缀和
        for (int i = n; i; --i) {
            b[i] += b[i + 1];
            a[i].y += b[i];
        }
        int max0 = 0, max1 = 0, ans = n; // ans为存活人数
        for (int i = n; i; --i) {
            if (a[i].x == 0) {
                max0 = max(max0, a[i].y);
                if (max1 > a[i].y)
                    --ans;
            }
            else {
                max1 = max(max1, a[i].y);
                if (max0 > a[i].y)
                    --ans;
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}