CF1055B 题解
CF1055B 题解
思路
其实就是一道用数组做的模拟题。
就用一个数组 \(a\) 记录第 \(i\) 根头发的长度,一个变量 \(ans\) 来记录目前捡的话要几秒钟,接下来就是要输入 \(a\) 数组,那其实也很简单,\(ans\) 就动态更新,如果前面一根头发不需要剪,而这根头发大于 \(l\),则 ans++
,因为其实将 \(ans\) 转化一下就是求 \(a\) 数组中有几个连续区间使得区间内的所有数都大于 \(l\),所以要是 \(a_i>l\) 并且 \(a_{i-1}\leqslant l\),则会多出一个区间。
然后初始化完了就要开始进行 \(m\) 次操作:
- 要是第一个数为 \(0\),则直接输出 \(ans\)。
- 要是第一个数是 \(1\),就要开始操作了:
首先,\(a_p=a_p+d\),然后就要开始更新 \(ans\),分为以下两种情况:
- 要是更新完的 \(a_p\) 大于 \(l\),并且 \(a_{p-1}\leqslant l,a_{p+1}\leqslant l\),则 \(a_p\) 为一个新的区间,因此
ans++
。 - 要是更新完的 \(a_p\) 大于 \(l\),并且 \(a_{p-1}>l,a_{p+1}>l\),则 \(a_p\) 让前面和后面的区间连在了一起(两个区间合二为一),因此
ans--
。
注意:上面两种情况都是原本的 \(a_p\) 小于等于 \(l\)。
总结
- 模拟。
- 数组基础。
- 分类讨论。
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
long long n,m,l,ans,a[100005],x,p,d;
int main(){
scanf("%lld %lld %lld",&n,&m,&l);
for(int i=1; i<=n; i++){
scanf("%lld",&a[i]);
if(a[i-1]<=l&&a[i]>l) ans++;//a[i]要剪,且a[i-1]不需要剪,则a[i]多创造出来了一个区间。
}
while(m--){//m次操作。
scanf("%lld",&x);
if(x==0) printf("%lld\n",ans);//直接输出答案,头发全都剪完了。
else{//某根头发又神经质的长长了。
scanf("%lld %lld",&p,&d);
a[p]+=d;//更新。
if(a[p]-d<=l){//原本是不需要剪的才可以,因为它如果原本就已经要剪的话它不管怎么长都是要剪的,而且那样ans不用变。
if(a[p]>l&&a[p-1]<=l&&a[p+1]<=l) ans++;//前后都是不需要剪的,所以这根头发创建了一个新区间。
if(a[p-1]>l&&a[p]>l&&a[p+1]>l) ans--;//前后都是要剪的,而因为原本a[p]不需要减,不属于前后两个区间,而现在,它不仅属于两个区间了,还把两个区间连起来了,所以区间数减少1。
}
}
}
return 0;
}