后缀数组写起来简单,理解也比较简单。如果在原来的基础之上发功,就算开始发功的人收益但当后续的发功结束后该来的终究会来,之前小于他的糖糖也会被灭掉,所以从后往前是可以的,还容易维护一些

#include <bits/stdc++.h>
using namespace std;
#define ll long long
struct node {
  ll a,b;
}m[50007];
ll c[1000007]={0};///后缀小数组
int main()
{
  ll t;
  scanf("%lld",&t);
  while (t--)
  {
    ll n,w;
    memset(c,0,sizeof(c));///初始化
    scanf("%lld%lld",&n,&w);
    for (register int i=1;i<=n;++i)
    {
      scanf("%lld%lld",&m[i].a,&m[i].b);
    }
    for (register int i=1;i<=w;++i)
    {
      int x;
      scanf("%d",&x);
      ++c[x];
    }
    ll ans=0;
    ll maxn_1=-1;
    ll maxn_0=-1;
    for (register int i=n;i>=1;--i)
    {
      c[i]+=c[i+1];///累计发功量
      m[i].b+=c[i];///发功
      if (m[i].a){
         if(maxn_1<m[i].b)///更新该组最大值
          {
             maxn_1=m[i].b;
          }
        if (m[i].b<maxn_0)///比较后面有无其他组最大值大于他
          ++ans;
      }
      else
      {
        if(maxn_0<m[i].b)
          maxn_0=m[i].b;
        if (m[i].b<maxn_1)
          ++ans;
      }
    }
    printf("%lld\n",n-ans);///所有减去死亡的 正难则反
  }
  return 0;
}