- 题意:给序列中的数添加正负号,使其和为0。
- 贪心:给序列中的数从大到小排序,然后正着扫一遍,维护一个当前和sum,若sum<=0,则加上当前数,反之减去当前数。
- 证明:假设最终有解,假设这个操作不成立,假设正确的操作是某一次连续加ai,aj,ai>=aj,之后做减法将ai和aj抵消,即将(ai-aj,2*aj)抵消,ai-aj可被抵消,因此上述贪心可行。
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,ans[100005];
struct mon{
int id,w;
}a[100005];
bool cmp(mon x,mon y)
{
return x.w>y.w;
}
int main()
{
while(cin>>n)
{
int sum=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i].w);
a[i].id=i;
}
sort(a+1,a+1+n,cmp);
for(int i=1;i<=n;i++)
{
if(sum<=0)
{
ans[a[i].id]=1;
sum+=a[i].w;
}
else{
ans[a[i].id]=-1;
sum-=a[i].w;
}
}
if(sum)
cout<<"No"<<endl;
else{
cout<<"Yes"<<endl;
cout<<ans[1];
for(int i=2;i<=n;i++)
cout<<' '<<ans[i];
cout<<endl;
}
}
return 0;
}