#计数#A 古老谜题
From NOIP2020 模拟赛 B 组 Day4
题目
给定一个长度为\(n\)的01序列\(a\),
问有多少个三元组\((l,p,r),1\leq l<p<r\leq n\)
满足\(a_p=1且s[l,p]=s[p,r](1的个数)\)
分析
由于确定\([l,r]\)就能确定\(p\),且实际上的限制条件为
\(s[l,r]\bmod 2=1且r-l>2\)
枚举右端点。
- 若当前位置为1,若前缀1的个数为奇数,实际上的贡献为之前前缀1的个数为偶数的位置,反之亦然
考虑用双指针维护区间1的个数必须超过2才能产生贡献 - 若当前位置为0,那就不只是上面的统计,有可能是两段连续的0夹着一个1,这个单独统计一下即可
代码
#include <cstdio>
#define rr register
using namespace std;
const int N = 1000011;
long long ans;
int a[N], n, tot, s1, s2, even, odd, now, last;
signed main() {
freopen("puzzle.in", "r", stdin);
freopen("puzzle.out", "w", stdout);
scanf("%*d%d", &n);
for (rr int i = 1; i <= n; ++i) {
rr char c = getchar();
while (c != 48 && c != 49) c = getchar();
a[i] = c ^ 48;
}
for (rr int r = 1, l = 0; r <= n; ++r) {
s1 += a[r];
while (s1 - s2 - a[l] > 2) s2 += a[l++], (s2 & 1) ? ++even : ++odd;
if (a[r]) {
(s1 & 1) ? ans += (now = odd) : ans += (now = even);
last = tot, tot = 0;
} else
++tot, ans += now + last;
}
return !printf("%lld", ans);
}