Hell on the Markets(貪心)
阿新 • • 發佈:2019-02-09
貪心部分的理論依據:前i個數可以湊出1~sum[i]的所有整數。
證明:
第二類數學歸納,n=1時成立,假設n=k之前所有項都成立,當n=k+1時。sum[k+1]=sum[k]+a[k+1]。只需證明能湊出sum[k]+1~sum[k+1]間的整數即可。設1≤p≤a[k+1],sum[k]+p=sum[k]+a[k+1]-(a[k+1]-p)。因為1≤a[i]≤i,易得sum[k]≥k,a[k+1]-p≤k。所以一定可以湊出a[k+1]-p。所以只需從之前湊出sum[k]裡面剪掉湊出a[k+1]-p的數就可以湊出sum[k]+p。所以從1~sum[k+1]都可以湊出。
輸入n個數,第i個數ai滿足1≤ai≤i。對每個數新增符號,使和值為0。
排序後從最大的數開始貪心就好。這次用了一些c++不常用的特性寫的,一開始缺了個頭檔案CE了。
#include<iostream> #include<algorithm> #include<iterator> using namespace std; const int maxn=100010; struct q{ int num,id; friend ostream& operator << (ostream &out,const q& x){ cout<<x.num; return out; } }; q a[maxn]; int main(){ int n; while(cin>>n){ long long sum=0; for(int i=0;i<n;++i){ a[i].id=i; cin>>a[i].num; sum+=a[i].num; } if(sum&1) {cout<<"No\n";continue;} sum>>=1; sort(a,a+n,[](q& a,q& b){return a.num>b.num;}); for(int i=0;i<n;++i){ if(a[i].num<=sum){ sum-=a[i].num; a[i].num=1; } else a[i].num=-1; } sort(a,a+n,[](q& a,q& b){return a.id<b.id;}); cout<<"Yes\n"; copy(a,a+n,ostream_iterator<q>(cout," ")); cout<<endl; } return 0; }