[CF] D. Array Division - Educational Codeforces Round 21
Solutions Codeforces 杂题 1900 Easy+
Lastmod: 2025-01-14 周二 21:53:19

https://codeforces.com/contest/808/problem/D

题目大意

给出 $n \ (n \le 10^5)$ 长的数组,其中元素 $1 \le a_i \le 10^9$ 问是否可以将其中某任意元素移动到其他任意位置,之后使得数组可以分成左右和相等的两部分。

简要题解

因为不增删数字,所以如果整个数组和为奇数无解。否则最后分成的最右两半,和是数组和的一半,记为 $Tar$。如果数组中存在 $Tar$ 则显然将其移动到开头或者结尾即可。 否则我们考虑最终分界的位置,则我们需要将某元素从分解左侧移出,或从分界右侧移入,我们根据前缀和和 $Tar$ 计算出元素的值,并查询其在左右是否存在即可。

注意这题都是正数,但其实有 $0$ 和负数也可以一样做。

特别的,因为和会溢出 int 如果使用 multiset 来存储前后的元素集合,在 count 查询时,可能导致 long long 被截短,而查询到本不该存在的值。

复杂度

$T$:$O(n log n)$

$S$:$O(n)$

代码实现

#include <bits/stdc++.h>
using namespace std;

int io_=[](){ ios::sync_with_stdio(false); cin.tie(nullptr); return 0; }();

using LL = long long;
using ULL = unsigned long long;
using LD = long double;
using PII = pair<int, int>;
using VI = vector<int>;
using MII = map<int, int>;

template<typename T> void cmin(T &x,const T &y) { if(y<x) x=y; }
template<typename T> void cmax(T &x,const T &y) { if(x<y) x=y; }
template<typename T> bool ckmin(T &x,const T &y) { 
    return y<x ? (x=y, true) : false; }
template<typename T> bool ckmax(T &x,const T &y) { 
    return x<y ? (x=y, true) : false; }
template<typename T> void cmin(T &x,T &y,const T &z) {// x<=y<=z 
    if(z<x) { y=x; x=z; } else if(z<y) y=z; }
template<typename T> void cmax(T &x,T &y,const T &z) {// x>=y>=z
    if(x<z) { y=x; x=z; } else if(y<z) y=z; }

// mt19937 rnd(chrono::system_clock::now().time_since_epoch().count());
// mt19937_64 rnd_64(chrono::system_clock::now().time_since_epoch().count());

/*
---------1---------2---------3---------4---------5---------6---------7---------
1234567890123456789012345678901234567890123456789012345678901234567890123456789
*/

const int INF = 0x3f3f3f3f;

void solve() {
  int n; cin >> n;
  vector<int> a(n);
  for (int& i : a) cin >> i;

  LL sum = 0;
  for (int i : a) {
    sum += i;
  }
  if (sum & 1) {
    cout << "NO\n";
    return;
  }

  multiset<int> lse, rse;
  for (int i : a) {
    rse.insert(i);
  }

  sum /= 2;

  if (rse.count(sum)) {
    cout << "YES\n";
    return;
  }

  LL cur = 0;
  for (int i : a) {
    cur += i;
    lse.insert(i);
    rse.erase(rse.find(i));
    if (cur < sum) {
      if (sum - cur < INF && rse.count(sum - cur)) {
        cout << "YES\n";
        return;
      }
    } else {
      if (cur - sum < INF && lse.count(cur - sum)) {
        cout << "YES\n";
        return;
      }
    }
  }
  cout << "NO\n";
}

int main() {
  int t = 1; 
  // cin >> t;
  while (t--) {
    solve();
  }
  return 0;
}
Prev: [CF] D. Mysterious Crime - Codeforces Round 519 by Botan Investments
Next: [CF] E. Selling Souvenirs - Educational Codeforces Round 21