The theoretical basis of the greedy part: the number of the former I can make up all the integers of 1~sum[i].
Proof: The second class of mathematical induction, n=1 when established, assuming n=k before all items are established when n=k+1. SUM[K+1]=SUM[K]+A[K+1].
Just prove that you can make up an integer between sum[k]+1~sum[k+1]. Set 1≤p≤a[k+1],sum[k]+p=sum[k]+a[k+1]-(a[k+1]-p).
Because 1≤a[i]≤i, easy to get sum[k]≥k,a[k+1]-p≤k. And because the known before the number of K can be 1~sum[k], so must be able to make up a[k+1]-p.
So just from the previous sum[k] inside cut out the number of a[k+1]-p to make up the sum[k]+p. So from 1~sum[k+1] All can be gathered out.
The implementation is the input when the sum, if it is an odd number of no solution, or else order, from large to small sweep over, select and for the SUM/2 of the symbol for the +, the rest is-.
Sort first, from big to small (otherwise it will decrease much)
Pay attention to sum with LL
#include <cstdio>#include<cstdlib>#include<algorithm>#include<iostream>using namespacestd;Const intmaxn=100005;structnode{intX,id;} A[MAXN];intANS[MAXN];BOOLCMP (node X,node y) {returnX.x>y.x;}intMain () {intN; intsum; while(SCANF ("%d", &n) = =1) { Long Longsum=0; for(intI=1; i<=n;i++) {scanf ("%d",&a[i].x); A[i].id=i; Sum+=a[i].x; } if(sum%2) {printf ("no\n"); Continue; } printf ("yes\n"); Sum/=2; Sort (a+1, A +1+n,cmp); for(intI=1; i<=n;i++) { if(a[i].x<=sum) {Ans[a[i].id]=1; Sum-=a[i].x; } ElseAns[a[i].id]=-1; } printf ("%d", ans[1]); for(intI=2; i<=n;i++) printf ("%d", Ans[i]); cout<<Endl; } return 0;}
uva1614 Hell on the