Codeforces Round 962 (Div. 3) E(思维 + 计数)

题面

给定一个长度为 n(1n2×105)01S,问:对于每一对 l,r(1lrn),有多少对 (x,y) 满足:lxyrSxy 中字符 1 的个数和字符 0 的个数相同。

题解

实际上,我们只需要找出每一对 (x,y),满足 Sxy 中字符 01 数量相同,看它对应的数对 (l,r) 的数量是多少,将所有的数对 (l,r) 的数量求和即可。

如果 (x,y) 确定下来了,那么 l 的可行范围在 [1,x]r 的可行范围在 [y,n],即:数对 (l,r) 的数量为 x×(ny+1)

我们可以把字符 0 看作数字 1,把字符 1 看作数字 1,然后做前缀和,将前 i 项的和记作 prei。如果 prei=prej,那么 Sij 中的字符 0 和字符 1 数量相同。

可以考虑枚举每个位置作为 r,然后将其贡献累加起来,对每一个 prei,记录其对应的 i 的和,这样,位置 j 作为 r,对答案的贡献就是 sumprej×(nj+1)

时间复杂度为 O(nlogn)

点击查看代码
#include <bits/stdc++.h>

using i64 = int64_t;

void solve() {
  std::string s;
  std::cin >> s;

  const int N = s.size();
  std::vector<int> pref(N + 1);
  for (int i = 0; i < N; i++) {
    pref[i + 1] = pref[i] + (s[i] == '0' ? -1 : 1);
  }

  std::map<int, i64> f;
  f[0] = 1;

  Z ans = 0;
  for (int i = 1; i <= N; i++) {
    // Z 是取模类的名字
    ans += Z(N - i + 1) * f[pref[i]];
    f[pref[i]] += i + 1;
  }
  std::cout << ans << "\n";
}

int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);

  int T;
  std::cin >> T;

  while (T--) {
    solve();
  }

  return 0;
}
posted @   yanhy-orz  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示