对于这一位置的糖糖能存活,当且仅当他编号后面的另一个组的糖糖的最大值≤它
对于发功,发功的作用会对1~i产生影响,也就是提高前面的能力值,我们大可以直接处理出来发功次数用完后的能力值。
为什么可以这样?因为如果前面的糖糖会被提前干掉,发功产生的影响其实是对前面的都进行增加的,是不影响前面会被打掉的人,只会影响前面没被打掉的是否会被该位置后面的干掉。
那么,对发功处理一个后缀和,倒序遍历所有糖糖更新能力值,同时更新两个组的最大值,比较当前位置的能力与另一个组的最大值即可。
#include<bits/stdc++.h> using namespace std; typedef long long ll; #define x first #define y second pair<ll,ll> a[1<<16]; ll cnt[1<<16]; int main(){ int t;cin>>t; while(t--){ int n,m;cin>>n>>m; for(int i=1;i<=n;i++) cin>>a[i].x>>a[i].y,cnt[i]=0; for(int i=1;i<=m;i++){ int q;cin>>q; cnt[q]++; } ll ma0=-1,ma1=-1; int ans=0; for(int i=n;i;i--){ cnt[i]+=cnt[i+1];///后缀和 a[i].y+=cnt[i];//更新当前糖糖的能力值 if(a[i].x==0){//组别为0 if(a[i].y>=ma1) ans++;//该位置后面的组别为1的最大值的是否≤当前位置的能力值 ma0=max(ma0,a[i].y);//更新组别0的最大值 } else { if(a[i].y>=ma0) ans++;//该位置后面的组别为0的最大值的是否≤当前位置的能力值 ma1=max(ma1,a[i].y);//更新组别1的最大值 } } cout<<ans<<endl; } }