I pondered this question for an hour, trying to beat sum/2 with a backpack, and found that the data was too large to store in the space.
Then I finally went to someone else's blog and found that there was a magical conclusion...
Fortunately, I didn't delve into it any more, I feel that this conclusion must be unexpected...
The conclusion is: when 1 <= a[i] <= i, the first i numbers must be able to make up all the integers from 1~sum[i]
See this for proof https://blog.csdn.net/wcr1996/article/details/43957461
When other bloggers have written this conclusion, just sort them, from big to small, add up to sum/2, if you can make it up, you can make it up in the end.
But I have been unable to figure out why it must be possible to make it up like this, why should it be sorted? ? Other blogs don't seem to have
give an explanation...
Then I thought about it for a long time and figured it out.
First of all, this conclusion proves that it can be beat into sum/2 (sum is an odd number regardless, output No)
Then, sort from largest to smallest.
Assuming that the first number that can be made up is a[k], a[k] is obviously the first number less than or equal to sum/2
That is to say, the numbers before a[k], that is, all numbers greater than a[k], are greater than sum/2
That is to say, it is impossible for these numbers to beat sum/2.
Then sum/2 subtracts a[k]. Then the number after a[k] must be sum/2-a[k];
why? Here is the key.
Because the numbers to add sum/2-a[k] must be less than sum/2-a[k], and these numbers must be after a[k]
Because a[k] is the first number less than or equal to sum/2, then the first number less than or equal to sum/2-a[k]
It must be less than or equal to a[k], and it must be behind a[k].
Therefore, the numbers to make up sum/2-a[k] are all after a[k], and these numbers have not been selected.
Because the conclusion at the beginning shows that sum/2-a[k] can definitely be summed up , and all needs to be summed up
The number of sum/2-a[k] has not been traversed yet.
Therefore, sum/2-a[k] must be made up of numbers that have not been traversed yet.
And so on, keep doing it, you can definitely get it done
over!!!!!!!!!!
#include<cstdio> #include<algorithm> #define REP(i, a, b) for(int i = (a); i < (b); i++) using namespace std; const int MAXN = 112345; int a[MAXN], id[MAXN], n; bool cmp(int x, int y) { return a[x] > a[y]; } intmain() { while(~scanf("%d", &n)) { long long sum = 0; REP(i, 0, n) { scanf("%d", &a[i]); sum += a[i]; id[i] = i; } if(sum & 1) { puts("No"); continue; } sort(id, id + n, cmp); sum >>= 1; REP(i, 0, n) { int t = id[i]; if(a[t] <= sum) { sum -= a[t]; a[t] = 1; } else a[t] = -1; } puts("Yes"); REP(i, 0, n) printf("%d ", a[i]); puts(""); } return 0; }