1. 程式人生 > >Uva 1614 - Hell on the Markets

Uva 1614 - Hell on the Markets

roman family int time pre 個數 所有 sum pos

鏈接:

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4489

題意:

輸入一個長度為n(n≤100000)的序列a,滿足1≤ai≤i,要求確定每個數的正負號,使得所有數的總和為0。
例如a={1, 2, 3, 4},則設4個數的符號分別是1, -1, -1, 1即可(1-2-3+4=0),但如果a={1, 2, 3, 3},則無解(輸出No)。

分析:

首先證明一個結論:所給的數可以湊出1~sum[n]之間的所有數。
當n = 1時結論成立,設當n = k時結論成立,則當n = k+1時,只需證明sum[k]+1 ~ sum[k+1]之間的所有數都可湊出。


設1≤x≤a[k+1],則sum[k]+x = sum[k]+a[k+1] - (a[k+1]-x)。因為x可由a[1]~a[k+1]湊出,所以0≤a[k+1]-x≤a[k+1]-1。
即所給的數可以湊出1~sum[n]之間的所有數。
知道了這個結論之後,貪心一下就好。

代碼:

 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 
 5 const int UP = 100000 + 5;
 6 struct NODE {
 7     int v, o, r; //值,編號,結果
 8     bool
operator < (const NODE& that) const { 9 return o < that.o; 10 } 11 } a[UP]; 12 13 bool cmp(const NODE& f, const NODE& b){ 14 return f.v > b.v; 15 } 16 17 int main(){ 18 int n; 19 for(int i = 0; i < UP; i++) a[i].o = i; 20 while(~scanf("%d", &n)){
21 long long sum = 0; 22 for(int i = 0; i < n; i++) scanf("%d", &a[i].v), sum += a[i].v; 23 24 if(sum % 2 != 0){ 25 printf("No\n"); 26 continue; 27 } 28 29 sum /= 2; 30 sort(a, a + n, cmp); 31 for(int i = 0; i < n; i++){ 32 if(sum - a[i].v < 0) a[i].r = -1; 33 else sum -= a[i].v, a[i].r = 1; 34 } 35 sort(a, a + n); 36 printf("Yes\n%d", a[0].r); 37 for(int i = 1; i < n; i++) printf(" %d", a[i].r); 38 printf("\n"); 39 } 40 return 0; 41 }

Uva 1614 - Hell on the Markets