NC14583 糖糖别胡说,我真的不是签到题目

原题地址:

https://ac.nowcoder.com/acm/problem/14583

基本思路:

我觉得这题的主要难点还是在搞懂这个题意吧,这个题意还是比较绕的而且还有一些细节要注意,两个关键点:从第i秒的时候,第i只糖糖就可以消灭掉所有排在他前面的和他不是同一组的且能力值小于他的糖糖,然后是这句 第i次发功的时间为ci,则在第ci秒结束后,b1,b2,.....,bci都会增加1.
我们从这两个关键点可以发现,这个发功实际上对于第i个糖糖能否消灭之前的糖糖本身是没有影响的,只是对之后的糖糖能否消灭之前存活的糖糖有关系,所以之后要消灭原来未消灭的就要比发功之后的能力值还要大,那么我们就能从后往前遍历,根据之后要消灭之前的要比之前的发功之后的大这个结论,我们先把每个糖糖发功后的能力值算出来,再反向遍历,看之后不同组的最大值是否比当前大就是了。

参考代码:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include <bits/stdc++.h>
using namespace std;
#define IO std::ios::sync_with_stdio(false)
#define ll long long
#define rep(i, l, r) for (int i = l; i <= r; i++)
#define per(i, l, r) for (int i = l; i >= r; i--)
#define mset(s, _) memset(s, _, sizeof(s))
#define pb push_back
#define pii pair <int, int>
#define mp(a, b) make_pair(a, b)
#define INF 0x3f3f3f3f

int n,m,x;
pii a[50050];
int memo[1000050];
signed main() {
  IO;
  int t;
  cin >> t;
  while(t--){
    cin >> n >> m;
    mset(memo,0);
    rep(i,1,n) cin >> a[i].first >> a[i].second;
    rep(i,1,m) { cin >> x; memo[x]++; }
    //从后往前加一下每个发功的贡献;
    per(i,n,1) memo[i] += memo[i + 1],a[i].second += memo[i];
    int mx_0 = 0,mx_1 = 0;
    int cnt = 0;
    per(i,n,1){
      //两个组分类一下;
      if(a[i].first){
        mx_1 = max(mx_1,a[i].second);
        if(mx_0 > a[i].second) cnt++;
      }else{
        mx_0 = max(mx_0,a[i].second);
        if(mx_1 > a[i].second) cnt++;
      }
    } 
    cout << n - cnt << '\n';
  }
  return 0;
}