首先感谢 PDSU----18计一-----周宁 ,我是看了这位大佬的解题,然后获取了一些思路。

题目意思:

第i个糖糖会有bi的能力值,然后他父亲能够在第i秒把1-i位置的b能力值都加1.

第i个糖糖在第i秒能干掉前面比他能力值小的人,并且是不用小组的,同一小组是不能干的。

小组最多就2组。

思路:首先我们需要先预处理父亲在每个时间点,对整体答案的影响。先计算算出来!

样例给出的是 bi:3 2 3 1 经过4秒钟之后的结果是 6 4 5 2

然后我们就发现,很显然,3号能攻击2号,因为5>4 并且2号和3号不在同一组

这样的话,我们从后往前就很好处理了

复杂度也降为O(n)

首先怎么处理父亲的时间点,bi增加的值,是父亲时间点的次数,应该从后往前进行求时间点的前缀和,然后给bi加上去。这样就把父亲的贡献给加上去了

接下来就是怎么计算那些人是没***掉的

因为总共就2组,我们可以从后往前跑,这样保证的是i<j,然后维护2个最大值,分别是第一组的最大值max1,第二组的最大值max2。我们这里的最大值是从后往前的最大值,并不是从前往后的最大值

如果当前这个点在第二组,如果比第一组的最大值还要大,那说明什么呢,这个点是不会被攻击到的,因为他比另一组的最大值还要大。

注意点: 初始化不要忘记

AC代码:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <map>
#include <queue>
#include <deque>
#include <set>
#include <stack>
#include <cctype>
#include <cmath>
#include <cassert>

using namespace std;

typedef long long ll;

const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}

const int N=50000+100;

int t;
int n,m;

int x,y;

int g[N];//分组

int a[N];//对应的能力 

int _time[N];

void init()
{
    memset(g,0,sizeof(g));
    memset(a,0,sizeof(a));
    memset(_time,0,sizeof(_time));
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        init();
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&x,&y);
            a[i]=y;
            g[i]=x;
        } 
        for(int i=1;i<=m;i++)
        {
            scanf("%d",&x);
            _time[x]++;
        }
        for(int i=n;i>0;i--)
        {
            _time[i]+=_time[i+1];//当前时间点发功了几次,相当于从后往前求前缀和
            //a[]: 3 2 3 1
        //time[]:  1 0 1 1 
            a[i]+=_time[i];
        }
//        for(int i=1;i<=n;i++)
//        {
//            printf("%d%c",a[i]," \n"[i==n]);
//        }
        int max1=-1;//表示第一组最大值 
        int max2=-1;//表示第二组最大值 
        int ans=0; 
        for(int i=n;i>=1;i--)
        {
            if(g[i]==0)
            {//0表示第一组 
                if(a[i]>=max2)
                {//如果当前的值大于第二组的最大值了,那么ans++;
                //也就是说当前这个点是不会被杀的 
                    ans++;
                } 
                if(a[i]>max1)
                {
                    max1=a[i];
                }
            }
            else 
            {
                if(a[i]>=max1)
                {//如果当前的值大于第二组的最大值了,那么ans++;
                    ans++;
                } 
                if(a[i]>max2)
                {
                    max2=a[i];
                }
            }
        } 
        printf("%d\n",ans);
    }
    return 0;
}