codeforces B. Roma and Changing Signs 解题报告

题目链接:http://codeforces.com/problemset/problem/262/B

题目意思:给出 n 个数和恰好一共要做的操作总数k。通过对n个数进行k次操作,每次操作可以把a[i] 转化为 -a[i](当然也可以对同一个数进行 <= k次操作)。问k次操作之后,整个序列的和最大为多少。

    首先要知道整个序列中数的分布是如何的,有3种情况:1、都为正数。此时k次操作只需要考虑序列中第一个数,因为它是最小的。  2、都为负数。容易想到,要尽可能把最小的负数变为相应的正数,如果变完之后,还没有到k次操作,那么就考虑负数和正数的交接处,看究竟是哪个数较小。

3、负正都有。这种情况和第2种情况处理类似。

     另外要注意n = 1,即整个序列只有一个数的情况。

    

 1 #include <iostream>
 2 #include <cstdlib>
 3 #include <cstdio>
 4 #include <cstring>
 5 using namespace std;
 6 
 7 const int maxn = 1e5 + 10;
 8 int a[maxn];
 9 
10 int main()
11 {
12     int n, k, i, ans, cnt;
13     while (scanf("%d%d", &n, &k) != EOF)
14     {
15         cnt = ans = 0;
16         for (i = 1; i <= n; i++)
17         {
18             scanf("%d", &a[i]);
19             ans += a[i];
20         }
21         if (a[1] >= 0 && a[n] >= 0)    // positive  
22         {
23             if (k % 2)            
24                 ans -= 2 * a[1];
25         }
26         else  // negative or ne+po
27         {
28             for (i = 1; i <= n; i++)
29             {
30                 if (a[i] < 0 && cnt < k)
31                 {
32                     ans -= 2 * a[i];
33                     cnt++;
34                 }
35                 else if (cnt >= k || a[i] >= 0)
36                     break;
37             }
38             if (cnt != k)
39             {
40                 k -= cnt;
41                 if (n != 1)
42                 {
43                     a[i] = (-a[i-1] > a[i] ? a[i] : -a[i-1]);  // 正负交接处哪个数更小
44                     if (k % 2)
45                         ans -= 2 * a[i];
46                 }
47                 else        // 整个序列只有1个数的情况
48                     if (k % 2)
49                         ans += 2 * a[1];    
50             }
51         }
52         printf("%d\n", ans);
53     }
54     return 0;
55 }

 

 

posted @ 2014-03-04 20:52  windysai  阅读(263)  评论(0编辑  收藏  举报