题意:


有n个糖糖,每个糖糖都有一个组别0或1,以及它的能力值。
在第i秒的时候,第i个糖糖就会干掉前面能力值比它小且非同组的糖糖 有m次发功,每次发功可以让前i个糖糖能力值+1


解法:


枚举暴力 从后往前遍历,依次更新糖糖的最大值,小于别组最大能力值的糖糖必然会干掉
问题在于如果解决不断发功更新的糖糖的能力值。仔细思考可以发现一个神奇的点,我们可以一口气把所有的发功都给使用完,而且不会从后往前遍历不会影响我们想要得到的结果(可以手动模拟一遍)。
所以利用差分获得发功后的能力值后,从后往前遍历一遍即可。


时间复杂度


O(n)


#include <algorithm>
#include <cstring>
using namespace std;

const int N = 5e4 + 7;

int a[N], b[N], c[N];
int n, m;

int main()
{
    ios::sync_with_stdio(false);
    int t;
    cin >> t;
    while (t--)
    {
        memset(b, 0, sizeof b);
        memset(c, 0, sizeof c);
        cin >> n >> m;
        for (int i = 1; i <= n; i++)
            cin >> a[i] >> b[i];
        for (int i = 1; i <= m; i++)  // 差分
        {
            int x;
            cin >> x;
            c[1]++, c[x + 1]--;
        }
        for (int i = 1; i <= n; i++)
        {
            c[i] += c[i - 1];
            b[i] += c[i];
        }
        
        int m0 = 0, m1 = 0, res = 0;
        for (int i = n; i >= 1; i--)
        {
            if (a[i] == 0)
            {
                m0 = max(m0, b[i]); // 更新当前最大能力值
                if (b[i] < m1) res++;
            }
            else if (a[i] == 1)
            {
                m1 = max(m1, b[i]);  // 更新当前最大能力值
                if (b[i] < m0) res++;
            }
        }
        
        cout << n - res << endl;
    }
    return 0;
}