CF466C 题解

Description

给定一个数组,求有多少组 \(i,j\) 将整个数组分成和相等的三个数组。

Solution

从左往右看一遍,记录每一个 \(i\) 使得 \(\sum_{k=1}^i a_k = \dfrac{S}{3}\)
从右往左看一遍,记录每一个 \(j\) 使得 \(\sum_{k=j}^n a_k = \dfrac{S}{3}\)
然后如果不出意外的话,每组 \(i,j\) 都是所求的数对,但要小心一点,就是 \(\{1,i\}\)\(\{j,n\}\) 两个区间可能交叉!所以要筛选出不交叉的区间。
怎样筛选呢?我定义一个当前指针 \(cur\) ,我扫到每一个 \(i\) 时,将 \(cur\) 移到满足第 \(cur\)\(j\) 的下标严格大于这个 \(i\) 的下标 \(+1\) ,则从 \(cur\) 及以后的所有 \(j\) 都能和当前 \(i\) 匹配。
为什么是下标 \(+1\) 呢?因为要给第二个区间留位置。

于是这个题目就做完了。记得开 \(long long\)

Code

#define int ll
int n, a[500010], ansl[500010], ansr[500010], cntl, cntr, ans, s[500010];

signed main() {
  int cur = 1;
  read(n);
  rep(i, 1, n) read(a[i]), s[i] = s[i - 1] + a[i];
  if(s[n] % 3) {
    print(0);
    goto end;
  }

  rep(i, 1, n) if(s[i] == s[n] / 3) ansl[++cntl] = i;
  rep(i, 1, n) if(s[n] - s[i - 1] == s[n] / 3) ansr[++cntr] = i;
  
  rep(i, 1, cntl) {
    while(ansr[cur] <= ansl[i] + 1 && cur <= cntr) ++cur;
    ans += cntr - cur + 1;
  }
  print(ans);

end:
  return 0;
}
posted @ 2021-07-02 16:37  1358id  阅读(52)  评论(0编辑  收藏  举报