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

传送门

题解: 核心就是满足条件,i<j and a[i]!=a[j] and b[i]<b[j] ; 另外有个附加属性,有一些发功的时间 i 第i秒会给在第i秒及以前出现的b[i]+1,

用一个sum[i]数组表示在此时间受到发功影响的次数的总和。那么问题就是变为 在i<j的条件下,b[i]+sum[j]-sum[i-1]<b[j]+sum[j]-sum[j-1];

两边同时去掉sum[j],即b[i]-sum[i-1]<b[j]-sum[j-1];ps:发功时间是第i秒的话,前面i-1秒的元素不会被影响。

只有两个组别,0和1,可以用a[i]^1来表达不同组。从后往前扫描,记录每组的最大值,与不同组的比较即可。

代码如下:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5;
int a[maxn];
int b[maxn];
int sum[maxn];
int ans;
int main(){
    int t,n,m,f;cin>>t;
    while(t--){
        ans=0;
        fill(sum,sum+maxn,0);
        fill(a,a+maxn,0);
        fill(b,b+maxn,0);
        cin>>n>>m;
        for(int i=1;i<=n;i++){
            scanf("%d%d",&a[i],&b[i]);
        }
        for(int i=1;i<=m;i++){
            scanf("%d",&f);
            sum[f]++;
        }
        for(int i=1;i<=n;i++){
            sum[i]+=sum[i-1];
            b[i]-=sum[i-1];
        }
        int ans=n;
        int c[2];c[0]=-0x3f3f3f;c[1]=-0x3f3f3f;
        for(int i=n;i>=1;i--){
            if(b[i]<c[a[i]^1])ans--;
            c[a[i]]=max(c[a[i]],b[i]);
        }
        cout<<ans<<endl;
    }
        return 0;
}

 

posted @ 2020-05-29 00:11  mohari  阅读(90)  评论(0编辑  收藏  举报