zoukankan      html  css  js  c++  java
  • Codeforces-808D Array Division 【multiset】

    Description

    Vasya has an array a consisting of positive integer numbers. Vasya wants to divide this array into two non-empty consecutive parts (the prefix and the suffix) so that the sum of all elements in the first part equals to the sum of elements in the second part. It is not always possible, so Vasya will move some element before dividing the array (Vasya will erase some element and insert it into an arbitrary position).

    Inserting an element in the same position he was erased from is also considered moving.

    Can Vasya divide the array after choosing the right element to move and its new position?

    Input

    The first line contains single integer n (1 ≤ n ≤ 100000) — the size of the array.

    The second line contains n integers a1, a2... an (1 ≤ ai ≤ 109) — the elements of the array.

    Output

    Print YES if Vasya can divide the array after moving one element. Otherwise print NO.

    Examples
    Input
    3
    1 3 2
    Output
    YES
    Input
    5
    1 2 3 4 5
    Output
    NO
    Input
    5
    2 2 3 4 5
    Output
    YES
    Note

    In the first example Vasya can move the second element to the end of the array.

    In the second example no move can make the division possible.

    In the third example Vasya can move the fourth element by one position to the left.


    题解:

    题意是给定一个数列,移动0或1个数字,使数列能从某个位置分开前后两半的和相等。我们可以假想有个隔板从左向右扫,每次两边的和的差值为x,若能找到某一边(看那边大)的一个数为x/2,则将它放到另一边就满足条件。扫一遍O(n),数据是无序的,如果暴力查找则总复杂度O(n^2)无法承受,我们可以维护两个平衡树做到O(nlogn),这里我们发现完全可以用STL的multiset代替。

    代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define INF 0x3f3f3f3f
     4 #define M(a, b) memset(a, b, sizeof(a))
     5 const int N = 100000 + 5;
     6 long long a[N];
     7 multiset<long long> s1, s2;
     8 multiset<long long>::iterator it;
     9 
    10 int main() {
    11     ios::sync_with_stdio(false);
    12     int n;
    13     while (cin >> n) {
    14         s1.clear(); s2.clear();
    15         long long sum = 0;
    16         for (int i = 1; i <= n; ++i) cin >> a[i], sum += a[i], s2.insert(a[i]);
    17         if (sum & 1) {cout << "NO
    "; continue;}
    18         long long sum1 = 0, sum2 = sum;
    19         if (s2.count(sum/2)) {cout << "YES
    "; continue;}
    20         bool flag = 0;
    21         long long temp;
    22         for (int i = 1; i <= n; ++i) {
    23             if (sum1 == sum2) {flag = 1; break;}
    24             if (sum1 < sum2) {
    25                 temp = sum2-sum1;
    26                 if (temp%2==0 && s2.count(temp/2)) {flag = 1; break;}
    27             }
    28             else {
    29                 temp = sum1-sum2;
    30                 if (temp%2==0 && s1.count(temp/2)) {flag = 1; break;}
    31             }
    32             sum1 += a[i]; s1.insert(a[i]);
    33             sum2 -= a[i]; it = s2.find(a[i]); s2.erase(it);
    34         }
    35         if (flag) cout << "YES
    ";
    36         else cout << "NO
    ";
    37 
    38     }
    39 
    40     return 0;
    41 }
  • 相关阅读:
    剑指Offer-30.连续子数组的最大和(C++/Java)
    剑指Offer-29.最小的K个数(C++/Java)
    UVA 1616 Caravan Robbers 商队抢劫者(二分)
    UVA 10570 Meeting with Aliens 外星人聚会
    UVA 11093 Just Finish it up 环形跑道 (贪心)
    UVA 12673 Erratic Expansion 奇怪的气球膨胀 (递推)
    UVA 10954 Add All 全部相加 (Huffman编码)
    UVA 714 Copying Books 抄书 (二分)
    UVALive 3523 Knights of the Round Table 圆桌骑士 (无向图点双连通分量)
    codeforecs Gym 100286B Blind Walk
  • 原文地址:https://www.cnblogs.com/robin1998/p/6864278.html
Copyright © 2011-2022 走看看