• BZOJ2288:[POJ Challenge]生日礼物——题解


    https://www.lydsy.com/JudgeOnline/problem.php?id=2288

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

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

    这题很像BZOJ1150:[APIO/CTSC2007]数据备份,但如果没有做过的话其实也不要紧。

    参考:https://www.cnblogs.com/zyfzyf/p/4114774.html感觉hzwer博客不是很好懂。

    我们首先将相同符号的点缩起来,去掉首末的负结点,然后思考。

    如果当前的正数个数<=m显然就求一遍和即可。

    如果>m的话就有两种选择了:

    1.忍痛割爱弃掉一个正数。

    2.选择一个负数,将两旁正数连同负数一起缩进来。

    我们发现这两个操作都是在原ans的基础上支付我们选择的点代价的,因此我们支付的代价越少越好,故我们将点权的abs放入小根堆里,每次拿出来之后和两边的点缩起来即可。

    #include<map>
    #include<cmath>
    #include<stack>
    #include<queue>
    #include<cstdio>
    #include<cctype>
    #include<vector>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int>pii;
    #define fi first
    #define se second
    const int N=1e5+5;
    const int INF=1e9+5;
    inline int read(){
        int X=0,w=0;char ch=0;
        while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
        while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        return w?-X:X;
    }
    struct node{
        int x,y;
        node(int xx=0,int yy=0){
            x=xx;y=yy;
        }
        bool operator <(const node &b)const{
            return abs(x)>abs(b.x);
        }
    };
    priority_queue<node>q;
    int n,m,cnt,tmp,a[N],b[N],pre[N],nxt[N];
    int main(){
        n=read(),m=read();
        for(int i=1;i<=n;i++){
            a[++tmp]=read();
            if(!a[tmp])tmp--;
        }
        
        b[++cnt]=a[1];
        for(int i=2;i<=tmp;i++){
            if((a[i]>0&&a[i-1]>0)||(a[i]<0&&a[i-1]<0))b[cnt]+=a[i];
            else{
                if(cnt==1&&b[cnt]<0)cnt--;
                b[++cnt]=a[i];
            }
        }
        if(b[cnt]<0)cnt--;
        
        int ans=0,tot=0;
        for(int i=1;i<=cnt;i++){
            if(b[i]>0)ans+=b[i],tot++;
            q.push(node(b[i],i));
        }
        
        for(int i=0;i<=cnt+1;i++)pre[i]=i-1,nxt[i]=i+1;
        pre[0]=0;nxt[cnt+1]=cnt+1;
        b[0]=b[cnt+1]=-INF;
        
        while(tot>m){
            node p=q.top();q.pop();
            if(b[p.y]!=p.x)continue;
            ans-=abs(p.x);
            b[p.y]=b[pre[p.y]]+b[nxt[p.y]]+p.x;
            b[pre[p.y]]=b[nxt[p.y]]=-INF;
            q.push(node(b[p.y],p.y));
            pre[p.y]=pre[pre[p.y]];nxt[pre[p.y]]=p.y;
            nxt[p.y]=nxt[nxt[p.y]];pre[nxt[p.y]]=p.y;
            tot--;
        }
        printf("%d
    ",ans);
        return 0;
    }

    +++++++++++++++++++++++++++++++++++++++++++

    +本文作者:luyouqi233。               +

    +欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/ +

    +++++++++++++++++++++++++++++++++++++++++++

  • 相关阅读:
    反悔贪心 学习笔记
    「CF901C」Bipartite Segments 题解
    「HEOI2015」公约数数列 题解
    拓展欧拉定理
    莫比乌斯反演题目选做
    八月水题录
    chapt15、使用虚拟内存
    chapt16、线程堆栈
    chapt14、探索虚拟内存
    get files version by vbs
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/9218994.html
Copyright © 2020-2023  润新知