题解 CF1428F Fruit Sequences
作者:互联网
给定一个 \(01\) 串,\(f(l, r)\) 是 \(l \to r\) 中最长的 \(1\) 连续子串的长度。求 \(\sum_{l=1}^n \sum_{r=l}^n f(l, r)\)
按照以前做那种单调栈题目的思维定式,肯定是考虑每一串左边到哪里,右边到哪里,在乘一乘贡献。
但是发现这个有点难搞啊,不一定是要一整串,其中的一小串依然是有贡献区间的,不能给连续整个的左右定个界限就好了。
还想着一串一串计算贡献?格局小了!
我们一个一个计算贡献!枚举一个左端点,一个个计算右端点贡献的和!
如果当前位是 \(0\),那显然不会令右端点的贡献和。如果是 \(1\),那么找到从这一位往右边最后一个连续串小于这个位置向右边连续的,右端点在这些位置的时候,对答案的贡献都是 \(1\),所以只要加上这一段的长度就好了。
比如 \(11101111\),那么加上最前面的一个 \(1\) 时,右端点在 \(\underline{111011}11\)(下划线划到的部分)的答案都会加上 \(1\),
至于维护,直接用数组在一段跑完的时候维护一下就好了。
说说很简单?自己想的时候根本想不到!!!妙啊!!!
% \(\textsf{ZhouAKngyang}\)
#include <iostream>
#define int long long
const int N = 500005;
int n, f[N], now, sum, ans;
char s[N];
signed main() {
std::cin >> n >> (s+1);
for (int i = 1; i <= n; i++) f[i] = n+1;
for (int i = n; i >= 1; i--) {
if (s[i] - '0') now ++, sum += f[now] - i;
else while (now) f[now] = i+now, now--;
ans += sum;
}
std::cout << ans;
}
标签:int,题解,sum,CF1428F,贡献,一串,Fruit,端点,now 来源: https://www.cnblogs.com/Acfboy/p/CF1428F.html