这道题写了好久,因为一个略傻缺的错误测了好久。。。
这道题我们需要抓住到一点:前面的糖糖会不会被消灭,只和后面的糖糖有关,所以,我们获取信息的顺序应该是从后开始,然后让前面的和后面比较。由于我们只需要知道会不会被消灭,所以,我们要的是后面的糖糖种的、类似最大值的东西。
那么,假设我们要比较两个糖糖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;
}
京公网安备 11010502036488号