zoukankan      html  css  js  c++  java
  • BZOJ2288: 【POJ Challenge】生日礼物

    2288: 【POJ Challenge】生日礼物

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 771  Solved: 238
    [Submit][Status][Discuss]

    Description

    ftiasch 18岁生日的时候,lqp18_31给她看了一个神奇的序列 A1, A2, ..., AN. 她被允许选择不超过 M 个连续的部分作为自己的生日礼物。

    自然地,ftiasch想要知道选择元素之和的最大值。你能帮助她吗?


    Input

    第1行,两个整数 N (1 ≤ N ≤ 105) 和 M (0 ≤ M ≤ 105), 序列的长度和可以选择的部分。

    第2行, N 个整数 A1, A2, ..., AN (0 ≤ |Ai| ≤ 104), 序列。

    Output

     

    一个整数,最大的和。

    Sample Input


    5 2
    2 -3 2 -1 2

    Sample Output

    5

    HINT

    Source

    【题解】

    把相连的负数和正数连起来,把0去掉。

    这个数组是正负正负.....这样的。不难证明一定是选择连起来后的数组中的若干段数。

    先把所有正数加合sum,记录正数的个数now。如果k < m,则sum即为答案。如果k > m,

    就要考虑两种决策:

    1、选择一个负数,让两个整数连成一段,now -= 1

    2、去掉一个正数,now -= 1

    可以发现,其实这两个决策都相当于sum减去数列中某一个数的绝对值。

    选了一个数后,这个数周围两个数不可再选。且要么选最小的数,要么选最小的数

    旁边的两个数。

    瞬间变成了BZOJ1150那个题目。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cstdlib>
     5 #include <queue>
     6 #include <vector>
     7 
     8 inline void read(int &x)
     9 {
    10     char ch = getchar(), c = ch;x = 0;
    11     while(ch < '0' || ch > '9')c = ch, ch = getchar();
    12     while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar();
    13     if(c == '-')x = -x;
    14 }
    15 
    16 const int INF = 0x3f3f3f3f;
    17 const int MAXN = 100000 + 10;
    18 const int MAXM = 100000 + 10; 
    19 
    20 int n,m,tmp,num[MAXN],cnt1,now,sum,cnt;
    21 int flag;
    22 
    23 struct Node
    24 {
    25     int pre,nxt,value;
    26     Node(int _pre, int _nxt, int _value)
    27     {
    28         pre = _pre;nxt = _nxt;value = _value;
    29     }
    30     Node(){}
    31 }node[MAXN * 4];
    32 
    33 int b[MAXN * 4];
    34 
    35 struct cmp
    36 {
    37     bool operator()(int a, int b)
    38     {
    39         return node[a].value > node[b].value;
    40     }    
    41 };
    42 
    43 std::priority_queue<int, std::vector<int>, cmp> q;
    44 
    45 int main()
    46 {
    47     read(n), read(m);
    48     while(tmp == 0)    read(tmp);
    49     if(tmp > 0)flag = 1;
    50     else flag = 0;
    51     num[++cnt1] += abs(tmp);
    52     for(register int i = 1;i <= n;++ i)
    53     {
    54         read(tmp);
    55         if(tmp == 0)continue;
    56         else if(tmp > 0 && !flag)++ cnt1, flag = 1;
    57         else if(tmp < 0 && flag)++ cnt1, flag = 0;
    58         num[cnt1] += tmp;
    59     }
    60     if(num[1] < 0)num[1] = INF;
    61     if(num[cnt1] < 0)num[cnt1] = INF;
    62     for(register int i = 1;i <= cnt1;++ i)
    63     {
    64         node[++cnt] = Node(cnt - 1, cnt + 1, abs(num[i]));
    65         if(num[i] > 0 && num[i] != INF)sum += num[i], ++now; 
    66         q.push(cnt);
    67     }
    68     node[0] = Node(0, 1, INF);
    69     ++ cnt;
    70     node[cnt] = Node(cnt - 1, 0, INF);
    71     while(q.size() && now > m)
    72     {
    73         int tmp = q.top(); q.pop();
    74         if(b[tmp])continue;
    75         int pre = node[tmp].pre, nxt = node[tmp].nxt;
    76         b[tmp] = b[pre] = b[nxt] = 1;
    77         sum -= node[tmp].value;-- now;
    78         ++ cnt;
    79         node[node[pre].pre].nxt = cnt;
    80         node[node[nxt].nxt].pre = cnt;
    81         node[cnt] = Node(node[pre].pre, node[nxt].nxt, node[pre].value + node[nxt].value - node[tmp].value);
    82     }
    83     printf("%d", sum);
    84     return 0;
    85 }
    BZOJ2288
  • 相关阅读:
    MongoDB 备份与恢复
    MongoDB 分片
    MongoDB 复制(副本集)
    MongoDB 聚合
    利用SSL For Free工具3分钟获取Let's Encrypt免费SSL证书
    使用免费SSL证书让网站支持HTTPS访问
    免费资源部落 免费SSL证书Let’s Encrypt安装使用教程:Apache和Nginx配置SSL
    Windows上管理远程Linux VPS/服务器文件工具
    SSH远程会话管理工具
    腾讯云linux服务器安装lnmp一键包
  • 原文地址:https://www.cnblogs.com/huibixiaoxing/p/7472101.html
Copyright © 2011-2022 走看看