牛客网【每日一题】4月21日题目精讲 糖糖别胡说,我真的不是签到题目

试题

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

时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 131072K,
其他语言262144K 64bit
IO Format:%lld

题目描述

从前,有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
输入

1 4 3 0 3 1 2 0 3 1 1 1 3 4

输出

3

题解:

我们先想想一个糖糖能活下来需要什么条件?
就是在它后面不存在一个比他的大的且不在一个组
两个要求:不能比他大且不在一组
这样我们其实就可以从后往前扫描,(因为这样扫描过的,不会再被消灭,我们就不用再管了),来维护当前位置往后每一组糖糖的最大值,然后比较,如果比这个位置大,这个位置的糖糖不就被消灭了

还有个发功问题(头大)
发功后并不是都+1,而是前ci个人+!,前ci个人之间的相对大小并没发生改变,所以不影响第ci个糖糖在第ci秒消灭他前面的糖糖。
而第ci之后的并没有+1,那咋办?我们可以用每个人最后的能力值来判断到底能不能存活
我们先求出每个糖糖最后的能力值,倒着判断每个糖糖是否能存活,用前缀和优化

具体看代码:

#include<bits/stdc++.h>
#define forr(n) for(int i=1;i<=n;i++)
typedef long long ll;
using namespace std;
const ll maxn=1e5+2;
ll t;
ll n,m;
ll s[maxn];
ll a[maxn];
ll b[maxn];
ll pre[maxn];
ll sum,maxx,maxx1;
int main(){
    
    cin>>t;
    while(t--){
        cin>>n>>m;
        forr(n)
		{
			 cin>>a[i]>>b[i];		 
		}
        forr(m)
		{
			ll w;
			cin>>w;
			 s[w]++;
		 }
          for(int i=n;i>=1;i--) pre[i]=pre[i-1]+s[i];

        for(int i=n;i>=1;i--){
			b[i]+=pre[i];
            if(!a[i]){
            	if(b[i]>maxx1) maxx1=b[i];//更新0队伍的最大值 
                if(b[i]<maxx) sum++;
             
            }
            else{
  				 if(b[i]>maxx) maxx=b[i];//更新1队伍最大值 
                if(b[i]<maxx1) sum++; 
            }
        }
        cout<<n-sum;
    }
    return 0;
}

/*
1
4 3
0 3
1 2
0 3
1 1
1
3
4
*/ 
posted @ 2020-04-26 00:21  回归梦想  阅读(97)  评论(0编辑  收藏  举报