从前,有n只萌萌的糖糖,他们分成了两组一起玩游戏。他们会排成一排,第i只糖糖会随机得到一个能力值bi。从第i秒的时候,第i只糖糖就可以消灭掉所有排在他前面的和他不是同一组的且能力值小于他的糖糖。
为了使游戏更加有趣,糖糖的爸爸,娇姐,会发功m次,第i次发功的时间为ci,则在第ci秒结束后,b1,b2,…,bci都会增加1.
现在,娇姐想知道在第n秒后,会有多少只糖糖存活下来。
输入:
第一行只有一个整数T(T<6),表示测试数据的组数。
第二行有两个整数n,m。表示糖糖的个数以及娇姐发功的次数。(1<=n<=50000,1<=bi<=1000000)
第三行到n+2行,每行有两个整数ai,bi,表示第i只糖糖属于那一组以及他的能力值。(0<=ai<=1,1<=bi<=1000000)
第n+3行到第n+m+2行,每行有一个整数ci,表示GTW第i次发功的时间.(1<=ci<=n)`
输出:
总共T行,第i行表示第i组数据中,糖糖存活的个数。
示例:
输入:
1
4 3
0 3
1 2
0 3
1 1
1
3
4
输出:
3
题意:
有n个人,分成两个队排成一排,
每个人都有一个能力值,第i个人的能力值为b[i]
第i秒,第i个人可以消灭排在他前面的另一个队且能力值小于他的人
有m次,前ci个人的能力值都可以加1,求最后有多少个人活下来
分析:
题目中比较复杂的是有m次可以增加能力值的机会,我们先不考虑消灭的问题,计算出最后所有人的能力值(这个不会影响最后的结果)。
由于题目中的n值较大,所以采用从前向后遍历,判断第i个人之前有没有不为同一队且能力值比他小的人,如果有设置标记,最后统计没有被标记的人数。这样时间复杂度为O(n^2),会超时。
因此,我们采用从后往前遍历,i从n~1,找到两个队当前的能力值的最大值,然后判断当前的人的能力值是否小于另一队的当前的能力最大值,如果是,则被消灭。最后统计被消灭的人数,得到存活的人数。时间复杂度为O(n)。
代码:
#include<bits/stdc++.h> //包含所有头文件
using namespace std;
#define ll long long
const int MAXN=50010;
int a[MAXN],sum[MAXN];
ll b[MAXN];
int main()
{
int T;
int n,m,c;
scanf("%d",&T);
while(T--)
{
memset(sum,0,sizeof(sum));
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d%lld",&a[i],&b[i]);
}
for(int i=1;i<=m;i++)
{
scanf("%d",&c);
sum[c]++;
}
for(int i=n;i>=1;i--)
{
sum[i]+=sum[i+1];
b[i]+=sum[i]; //计算最后每个糖糖的能力值
}
ll max0=0,max1=0;
int cnt=0;
for(int i=n;i>=1;i--)
{//从后往前遍历
if(a[i]==0)
{
max0=max(max0,b[i]);
if(max1>b[i]) cnt++;
} else{
max1=max(max1,b[i]);
if(max0>b[i]) cnt++;
}
}
printf("%d\n",n-cnt);
}
return 0;
}