牛客-小d和孤独的区间
题目如上
1 s 1s 1s的时间限制,说明我们应该找到一种“巧法”
根据提示,我们只需要找到“中间全部都是 0 0 0,只有一个1的区间”即可
但是在找的途中,我们不仅要顾及当前 1 1 1之前的 0 0 0的个数,我们还要注意顾及 1 1 1之后的
代码:
#include<iostream>
using namespace std;int n;int main() {cin >> n;long long res = 0;//必须要开long long//index存最新的1的下标,cnt存0的个数加上当前1本身long long index = 0; long long cnt = 0;for (int i = 1; i <= n; i++) { //变读入边运算int a;cin >> a;if (a) { //如果读到了1cnt = i - index; //更新一下这个1和前面的1之间的0的个数index = i; //记录下这个1的位置}res += cnt; //每次循环都让答案加上cnt}cout << res;return 0;
}
或许你会一头雾水,为什么每次都要加上 c n t cnt cnt ?而不是当 a a a等于 1 1 1的时候或者是 a a a等于 0 0 0的时候之类的。
我们以一组输入为例:为了顾及理解的方便,此数是比较特殊的情况。
5
0 0 1 0 0
我们拿出笔对其进行模拟。
首先,我们输入了前两个 0 0 0,这时候变量都没有任何改变。
当我们输入第三个 1 1 1的时候, c n t cnt cnt变为了 3 3 3,之后 i n d e x index index变为了 3 3 3。这时候答案加上了 3 3 3。
**这时候的三包含了什么含义?**首先,在一个只有一个1的区间之中,每个0都与1产生了一个区间,在此例子中便是:0 0 1
( [ 1 , 3 ] ), ([ 1 , 3 ]), ([1,3]),0 1
( [ 2 , 3 ] ), ([ 2 , 3 ]), ([2,3]),在之后,每个1都可以自己组成一个区间,那么就正好是 3 3 3个区间。
之后我们又输入了两个 0 0 0,然后我们的答案加了两次 3 3 3,为什么?
我们从第四个 0 0 0开始看,当我们增加这一个 0 0 0之后,前面的 0 0 0与这个 0 0 0可以联动起来,能够再次组成三个区间,即:
0 0 1 0
( [ 1 , 4 ] ), ([ 1 , 4 ]), ([1,4]),0 1 0
( [ 2 , 4 ] ), ([ 2 , 4 ]), ([2,4]),1 0
( [ 3 , 4 ] ), ([ 3 , 4 ]), ([3,4]),故我们可以得到一个结论,在这之后,每增加 1 1 1个 0 0 0,都会增加 i n d e x index index指向的1的前面 0 0 0与 1 1 1能够组成的区间数。
由此我们就可以得到代码。