首页 > 其他 > 详细

【贪心】 51nod 1053 最大M字段和 V2

时间:2015-10-01 20:25:07      阅读:263      评论:0      收藏:0      [点我收藏+]

通道

思路:可以发现这序列是一段上升一段下降的锯齿形。先考虑拿到所有正数,此时如果段数大于m,考虑怎么最小代价减少段的数量,从 负数和最小的开始合并?而且要考虑负数和超过正数和的情形,注意特殊情况是这段和为0时,并不需要合并,直接跳过。减小个数的方案是,要么这段大于0,去掉这个及左右2边,并合并,这样可能会给后面的答案贡献更小的答案;要么这段小于0,就是将左右2边大于0的合并减少了1个区间。

代码:

技术分享
#include <cstdio>
#include <cstring>
#include <set>
#include <algorithm>
using namespace std;

typedef long long ll;

template <class T>
inline bool rd(T &ret) {
    char c; int sgn;
    if(c = getchar() , c == EOF) return false;
    while(c != - && (c < 0 || c > 9)) c = getchar();
    sgn = (c == -) ? -1 : 1;
    ret = (c == -) ? 0 : (c - 0);
    while(c = getchar(), c >= 0 && c <= 9) ret = ret * 10 + (c - 0);
    ret *= sgn;
    return true;
}

const int N = 2000005;

ll s[N];
set<pair<ll, int> > a;
int n, m, now;
int pr[N], ne[N];

void Erase(int x) {
    int l = pr[x], r = ne[x];
    if (l) ne[l] = r;
    if (r) pr[r] = l;
}
int main() {
    rd(n), rd(m);
    ll tem = 0, ans = 0;
    int cnt = 0;
    for(int i = 1, x; i <= n; ++i) {
        rd(x);
        if((tem < 0 && x > 0) || (tem > 0 && x < 0)) {
            now += tem > 0;
            s[++cnt] = tem;
            a.insert(make_pair(abs(tem), cnt));
            tem = 0;
        }
        tem += x;
        ans += x > 0 ? x : 0;
    }
    now += tem > 0;
    s[++cnt] = tem;
    a.insert(make_pair(abs(tem), cnt));
    for( int i = 1; i <= cnt; ++i) 
        pr[i] = i - 1, ne[i] = i + 1;
    ne[cnt] = s[0] = 0;
    while (now > m) {
        int x = (*a.begin()).second;
        a.erase(make_pair(abs(s[x]), x));
        if (s[x] < 0 && (!pr[x] || !ne[x]) || !s[x]) continue;
        a.erase(make_pair(abs(s[pr[x]]), pr[x])),a.erase(make_pair(abs(s[ne[x]]), ne[x]));
        ans -= abs(s[x]);
        s[x] = s[x] + s[pr[x]] + s[ne[x]];
        Erase(pr[x]), Erase(ne[x]);
        a.insert(make_pair(abs(s[x]), x));
        --now;
    }
    printf("%I64d\n", ans);
    return 0;
}

/*
7 2
-2 11 -4 13 -5 6 -2
7 2
1 -10 2 -9 3 -8 4
6 1
1 -1 1 -1 1 -1
*/
View Code

 

【贪心】 51nod 1053 最大M字段和 V2

原文:http://www.cnblogs.com/Rojo/p/4851387.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!