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

题目

题目描述

从前,有 n 只萌萌的糖糖,他们分成了两组一起玩游戏。他们会排成一排,第 i 只糖糖会随机得到一个能力值 bi。从第 i 秒的时候,第 i 只糖糖就可以消灭掉所有排在他前面的和他不是同一组的且能力值小于他的糖糖。

为了使游戏更加有趣,糖糖的爸爸,娇姐,会发功 m 次,第 i 次发功的时间为 ci ,则在第 ci 秒结束后 b1,b2,.....,bci 都会增加 1

现在,娇姐想知道在第 n 秒后,会有多少只糖糖存活下来。

输入描述

第一行只有一个整数 TT<6) ,表示测试数据的组数。
第二行有两个整数 n,m 。表示糖糖的个数以及娇姐发功的次数。(1n50000,1bi1000000
第三行到 n+2 行,每行有两个整数 ai,bi ,表示第 i 只糖糖属于那一组以及他的能力值。(0ai1,1bi1000000
n+3 行到第 n+m+2 行,每行有一个整数 ci ,表示GTW第 i 次发功的时间.(1cin)

输出描述

总共 T 行,第 i 行表示第 i 组数据中,糖糖存活的个数。

示例1

输入

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

输出

3

题解

知识点:枚举,前缀和,差分。

每一只糖糖的状态之和后面的糖糖有关,从正向遍历每次要重复考虑之前区间糖糖的状态,从反向遍历可以通过更新已遍历区间的最大值来决定遍历到的糖糖的状态。

i 次发功后会造成 [0,ci] 糖糖数值加一,显然每次增加不会影响后面的糖糖状态。正向遍历每次都给对应区间整体加一,不能满足复杂度;反向遍历用 delta 来记录到某个糖糖为止增加的次数,从而在之后用 bi+delta 代替 bi 达到增加的效果。

时间复杂度 O(n+m)

空间复杂度 O(n+m)

代码

#include <bits/stdc++.h>
using namespace std;
bool a[50007];
int b[50007];
int c[50007];
int main(){
std::ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int T;
cin>>T;
while(T--){
int n,m;
cin>>n>>m;
for(int i = 1;i<=n;i++){
c[i] = 0;
cin>>a[i]>>b[i];
}
for(int i = 0;i<m;i++){
int tmp;
cin>>tmp;
c[tmp]++;
}
int delta = 0,ans = n,max0 = 0,max1 = 0;
///一个糖糖的死活只和后面糖糖最大值有关
for(int i = n;i>=1;i--){
delta+=c[i];///区间增值是向前的,所以可以逆向累加
if(a[i]){
ans -= (b[i]+delta)<max0;
max1 = max(b[i]+delta,max1);
}
else{
ans -= (b[i]+delta)<max1;
max0 = max(b[i]+delta,max0);///更新最大值为当前值+增值
}
}
cout<<ans<<'\n';
}
return 0;
}
posted @   空白菌  阅读(45)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
点击右上角即可分享
微信分享提示