这道题写了好久,因为一个略傻缺的错误测了好久。。。
这道题我们需要抓住到一点:前面的糖糖会不会被消灭,只和后面的糖糖有关,所以,我们获取信息的顺序应该是从后开始,然后让前面的和后面比较。由于我们只需要知道会不会被消灭,所以,我们要的是后面的糖糖种的、类似最大值的东西。
那么,假设我们要比较两个糖糖i和j(i<j),那么,我们确定i会不会被消灭的时候,我们比较的式子就是:
b[i]+sum[j]-sum[i-1]<=>b[j]+c[j]
我们变一下式,就变成:
b[i]-sum[i-1]<=>b[j]+c[j]-sum[j]
这时候,式子右边的就是我们要找的定值。那么,每次查询一个位置的时候,计算一下这个位置的b[j]+c[j]-sum[j]与目前该队里的最大值做比较,选择是否替代。
另外,还需要几个特判:有对手队还没有出现,可以continue跳过判断。如果这是本队出现的第一个,就直接取值等等。就直接看代码吧。
#include <iostream> #include <cstdio> #include <map> #include <cstring> #include <climits> const int INF = 0x3F3F3F3F; #define MEM(a) memset(a,0,sizeof(a)) #define rep(i,a,b) for(register int i=a;i<=b;++i) #define per(i,a,b) for(register int i=b;i>=a;--i) using namespace std; typedef long long ll; const int maxn=1000000+10; int a[maxn],b[maxn],c[maxn]; int n,m; int sum[maxn]; int read() { char ch=getchar();int x=0,f=1; while(ch<'0' || ch>'9') {if(ch=='-')f=-1;ch=getchar();} while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int main() { /* 6 5 5 0 0 0 3 0 4 1 4 1 1 1 2 3 4 5 */ //freopen("inin.txt","r",stdin); int _; _=read(); while(_--){ MEM(c); n=read(),m=read(); ll dec=0; ll p0=-1,p1=-1; rep(i,1,n){ a[i]=read(); b[i]=read(); } rep(i,1,m){ int t; //scanf("%d",&t); t=read(); c[t]++; } rep(i,1,n){ sum[i]=sum[i-1]+c[i]; } per(i,1,n){ if(a[i]==1){ if(p1==-1){ p1=i; } if(b[p1]+c[p1]-sum[p1]<=b[i]+c[i]-sum[i]){ p1=i; } if(p0==-1) continue; if(b[i]+sum[p0]-sum[i-1]<b[p0]+c[p0]){ dec++; } } else if(a[i]==0){ if(p0==-1){ p0=i; } if(b[i]+c[i]-sum[i]>=b[p0]+c[p0]-sum[p0]){ p0=i; } if(p1==-1) continue; if(b[i]+sum[p1]-sum[i-1]<b[p1]+c[p1]){ dec++; } } } printf("%d\n",n-dec); } return 0; }