题意
给出n个数字a[i], 并且 1 <= a[i] <= i,通过每一项乘以1或-1,使得所有数字的乘积和为0;
分析
题意化简:从数组中找出若干个数,使他们的和为所有数和的一半。
想了n种超时的算法,毫无头绪。
肯定得用上 1 <= a[i] <= i; 这一个条件。
只是不知从何下手。
原来有个结论: 在前i个数中,能够组成1~sum[i] 任意一个数。证明过程其实对程序没有影响,结论只是为了证明倒序构造,结果的正确性。
倒序构造。。。
有一个巨大的坑点。。所有数的和为long long,用int WA了6次。。
代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+19;
int a[maxn], n;
int r[maxn];
bool cmp(int x, int y)
{
return a[x] < a[y];
}
int main()
{
//freopen("in.txt","r", stdin);
while(cin >> n )
{
long long cnt = 0;
for(int i = 0; i < n;i ++)
{
cin >> a[i];
cnt += a[i];
r[i] = i;
}
if(cnt % 2 == 1)
{
puts("No");
continue;
}
sort(r,r+n,cmp);
cnt >>= 1;
for(int i = n-1; i >= 0; i--)
{
int j = r[i];
if(a[j] <= cnt)
{
cnt -= a[j];
a[j] = 1;
}
else
a[j] = -1;
}
puts("Yes");
for(int i = 0; i < n-1; i++)
cout << a[i] << " ";
cout << a[n-1] << endl;
}
return 0;
}