题意: 给出一个长度为n的数列,要求从中取出不超过m段连续的数,使其和最大。
n<=100000

解题方法:
这题可以把一段同号的数并成一个数,那么就变成了一个正负交替的序列,然后把头尾的负数去掉。
有一种想法就是把所有的正值都加起来,然后把所有数的绝对值加进优先队列,每次去一个最小的出来然后减掉,最后的即为答案。
为什么是正确的呢?因为如果减去的值在原数列中为正则相当于不要这个数,否则就相当于选了这个负数然后把两边的正值合并起来。
但有一个问题,就是若选了一个数那么其两边的数就必定不能被选,那么就转换成了数据备份了。
题解参考的hzwer大牛的,orz

//bzoj 1150
#include <bits/stdc++.h>
using namespace std;
const int inf = 0x7fffffff;
const int maxn = 100010;
typedef long long LL;
inline int read()
{
    char ch=getchar();
    int f=1,x=0;
    while(!(ch>='0'&&ch<='9')){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+(ch-'0');ch=getchar();}
    return x*f;
}
inline LL llread(){
    char ch=getchar();
    LL f=1,x=0;
    while(!(ch>='0'&&ch<='9')){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+(ch-'0');ch=getchar();}
    return x*f;
}
struct node{
    int pos, v;
    node(){}
    node(int pos, int v) : pos(pos), v(v) {}
    bool operator < (const node &rhs) const{
        return v > rhs.v;
    }
};
priority_queue <node> que;
int n, m, a[maxn], b[maxn], L[maxn], R[maxn], vis[maxn];

int main(){
    n = read(); m = read();
    for(int i = 1; i <= n; i++) b[i] = read();
    int n1 = 1;
    a[1] = b[1];
    for(int i = 2; i <= n; i++){
        if(a[n1] <= 0 && b[i] <= 0) a[n1] += b[i];
        else if(a[n1] >= 0 && b[i] >= 0) a[n1] += b[i];
        else a[++n1] = b[i];
    }
    if(a[n1] <= 0) n1--;
    if(a[1] <= 0){
        for(int i = 1; i < n1; i++){
            a[i] = a[i+1];
        }
        n1--;
    }
    n = n1;
    int cnt = 0, ans = 0;
    for(int i = 1; i <= n; i++){
        if(a[i] > 0){
            cnt++;
            ans += a[i];
        }
        que.push(node(i, abs(a[i])));
        a[i] = abs(a[i]);
        L[i] = i - 1;
        R[i] = i + 1;
    }
    R[n] = L[1] = 0;
    if(cnt <= m){
        printf("%d\n", ans);
        return 0;
    }
    m = cnt - m;
    for(int i = 1; i <= m; i++){
        node now = que.top(); que.pop();
        while(vis[now.pos] && !que.empty()) {now = que.top(); que.pop();}
        if(vis[now.pos]) break;
        ans -= now.v;
        if(que.empty()) break;
        int x = now.pos;
        if(!R[x]){
            vis[x] = 1; vis[L[x]] = 1;
            R[L[L[x]]] = 0;
        }
        else if(!L[x]){
            vis[x] = 1; vis[R[x]] = 1;
            L[R[R[x]]] = 0;
        }
        else{
            node nxt;
            vis[L[x]] = vis[R[x]] = 1;
            nxt.v = a[x] = a[R[x]] + a[L[x]] - a[x];
            nxt.pos = x;
            que.push(nxt);
            if(R[R[x]]) L[R[R[x]]] = x;
            if(L[L[x]]) R[L[L[x]]] = x;
            L[x] = L[L[x]];
            R[x] = R[R[x]];
        }
    }
    printf("%d\n", ans);
    return 0;
}