因为 1 <= a[i] <= i,可用数学归纳法证明,用 a[1]-a[i] 的部分或全部元素通过求和,一定可以凑出 1-sum[i] 的每个整数(sum[i]是前 i 个元素的和)
所以只需排序后从最大的元素(假设为k)开始,凑出sum/2即可。用去掉了k的集合,一定可以凑出sum/2 - a[k],所以不用担心贪心到最后凑不出来。只要sum是偶数,就一定会有解。
Run Time: 0.339s
#define UVa "8-10.1614.cpp" //Hell on the Markets
char fileIn[30] = UVa, fileOut[30] = UVa;
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
struct Contract {
int v, id;
bool operator < (const Contract& c) const {
return v < c.v;
}
};
int main() {
int n;
while(scanf("%d", &n) != EOF) {
const int maxn = 100000 + 10;
Contract a[maxn];
int b[maxn];
long long sum = 0;
int tmp;
for(int i = 0; i < n; i ++) {
scanf("%d", &tmp);
a[i].id = i;
a[i].v = tmp;
sum += tmp;
}
memset(b, -1, sizeof(b));
sort(a, a + n);
if(sum%2) printf("No\n");
else {
sum /= 2;
for(int i = n-1; i >= 0; i --) {
if(sum >= a[i].v) {
sum -= a[i].v;
b[a[i].id] = 1;
}
else if(sum == 0) break;
}
printf("Yes\n");
for(int i = 0; i < n; i ++) printf("%d%c", b[i], (i==n-1)?'\n':' ');
}
}
return 0;
}