#计数#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的个数为偶数的位置,反之亦然
    考虑用双指针维护区间1的个数必须超过2才能产生贡献
  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);
}
posted @ 2020-10-13 16:18  lemondinosaur  阅读(101)  评论(0编辑  收藏  举报