题目大意:一个整数序列a,1≤a[i]≤i。问能否通过在一些元素前加上负号,使得整个序列和为0。
题目分析:贪心。贪心策略:每次都先选最大的元素加负号(或保留,不加负号)。
贪心依据:对于1≤a[i]≤i,1~sum[i]总能表示出来。
贪心依据证明:用数学归纳法证明,当i=1时,显然成立。假设当i=k时,也成立。当i=k+1时,(先证明到这儿,有空再补)。
代码如下:
# include<iostream> # include<cstdio> # include<cstring> # include<algorithm> using namespace std; struct Num { int val,id; bool operator < (const Num &a) const { return val<a.val; } }; Num num[100005]; int n,mark[100005]; void solve(int u) { for(int i=n-1;i>=0;--i){ if(u-num[i].val==0){ mark[num[i].id]=1; return ; }else if(u-num[i].val>0){ u-=num[i].val; mark[num[i].id]=1; } } } int main() { long long sum; while(scanf("%d",&n)==1) { memset(mark,0,sizeof(mark)); sum=0; for(int i=0;i<n;++i){ scanf("%d",&num[i].val); num[i].id=i; sum+=num[i].val; } if(sum&1){ printf("No "); continue; } sort(num,num+n); solve(sum/2); printf("Yes "); for(int i=0;i<n;++i) printf("%d%c",mark[i]?1:-1,(i==n-1)?' ':' '); } return 0; }