Educational Codeforces Round 21 Problem D(Codeforces 808D)
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?
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.
Print YES if Vasya can divide the array after moving one element. Otherwise print NO.
3
1 3 2
YES
5
1 2 3 4 5
NO
5
2 2 3 4 5
YES
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.
我很好奇,我和同学内部玩Virtual Contest的时候有个人读不懂前三题,偏偏这道题我读错了,他读懂。最后看到题目描述最后一句话中的element,单数!才发现只能移动一个,内心极其崩溃绝望,但还是在10分钟赶出了程序。
题目大意是说,给定一个数列,将一个数移动到另一个位置或者什么都不做,是否使得这个数列能被划分成2个部分。
记两个sum,一个是左边求和的sum,还有一个是另一边求和的sum。最开始左边的sum为0,右边的和为整个数列的和,然后依次将下一个数添加进左边,在右边删去这个数并修改sum,再判断两个sum是否相等,如果相等就可以简单地puts("YES"),然后exit(0)了,如果不相等,就判断差是否为奇数,如果不是就看看和大的那一边存不存在值为差的一半的数(存在就把它拿到小的那一边,就可以使和相等了),如果存在就输出YES退出程序。循环结束了,直接输NO就好了。
至于判断这个数存不存在,交给可重集就好了。
Code
1 /** 2 * Codeforces 3 * Problem#808D 4 * Accepted 5 * Time:15ms 6 * Memory:0k 7 */ 8 #include<iostream> 9 #include<cstdio> 10 #include<ctime> 11 #include<cctype> 12 #include<cstring> 13 #include<cstdlib> 14 #include<fstream> 15 #include<sstream> 16 #include<algorithm> 17 #include<map> 18 #include<set> 19 #include<stack> 20 #include<queue> 21 #include<vector> 22 #include<stack> 23 using namespace std; 24 typedef bool boolean; 25 #define inf 0xfffffff 26 #define smin(a, b) a = min(a, b) 27 #define smax(a, b) a = max(a, b) 28 #define max3(a, b, c) max(a, max(b, c)) 29 #define min3(a, b, c) min(a, min(b, c)) 30 template<typename T> 31 inline boolean readInteger(T& u){ 32 char x; 33 int aFlag = 1; 34 while(!isdigit((x = getchar())) && x != '-' && x != -1); 35 if(x == -1) { 36 ungetc(x, stdin); 37 return false; 38 } 39 if(x == '-'){ 40 x = getchar(); 41 aFlag = -1; 42 } 43 for(u = x - '0'; isdigit((x = getchar())); u = (u << 1) + (u << 3) + x - '0'); 44 ungetc(x, stdin); 45 u *= aFlag; 46 return true; 47 } 48 49 #define LL long long 50 51 int n; 52 int* a; 53 LL sum = 0; 54 multiset<LL> s; 55 multiset<LL> s1, s2; 56 57 inline void init() { 58 readInteger(n); 59 a = new int[(const int)(n + 1)]; 60 for(int i = 1; i <= n; i++) { 61 readInteger(a[i]); 62 sum += a[i]; 63 s.insert(sum); 64 s2.insert(a[i]); 65 } 66 } 67 68 LL sum1 = 0, sum2 = 0; 69 70 inline void solve() { 71 if(sum & 1) { 72 puts("NO"); 73 return; 74 } 75 sum2 = sum; 76 sum /= 2; 77 if(s.count(sum)) { 78 puts("YES"); 79 return; 80 } 81 for(int i = 1; i <= n; i++) { 82 if(sum1 > sum2) { 83 LL temp = sum1 - sum2; 84 if((temp & 1) == 0 && s1.count(temp / 2)) { 85 puts("YES"); 86 return; 87 } 88 } else { 89 LL temp = sum2 - sum1; 90 if((temp & 1) == 0 && s2.count(temp / 2)) { 91 puts("YES"); 92 return; 93 } 94 } 95 sum1 += a[i], sum2 -= a[i]; 96 s1.insert(a[i]), s2.erase(s2.find(a[i])); 97 } 98 puts("NO"); 99 } 100 101 int main() { 102 init(); 103 solve(); 104 return 0; 105 }