zoukankan      html  css  js  c++  java
  • set+链表 【POJ Challenge】生日礼物

    2288: 【POJ Challenge】生日礼物

    Time Limit: 10 Sec Memory Limit: 128 MB
    Submit: 841 Solved: 255
    [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

    可以发现,连续的一段同号整数一定被一起选上.所以把连续的整数合并,去掉0.
    先选上所有的正数段,如果段数<=m,直接输出,如果大于,就需要添上一段负数使两个正数段连在一起,或者去掉一段正数。所以把所有数改成正数,用set选最小的。
    而且不能选连续的两段,如果左右端点是负数,选他没必要,不能选。
    具体怎么搞,见这个题解(思路相同)

    #pragma GCC optimize("O3")
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<set>
    #include<cmath>
    #define N 100005
    #define ll long long
    using namespace std;
    int n,m,num,tot;
    int fro[N],nex[N];
    struct node
    {
        int id;ll h;
        node(){}node(int x,ll y){id=x;h=y;}
        inline friend bool operator <(const node &x,const node &y){return (x.h!=y.h)?x.h<y.h:x.id<y.id;}
    };set<node> s;
    ll a[N],ans;
    int main()
    {
        scanf("%d%d",&n,&m);ll x;
        for(int i=1;i<=n;i++)
        {
            scanf("%lld",&x);if(x==0)continue;
            if(tot==0){a[++tot]=x;continue;}
            if((x>0&&a[tot]>0)||(x<0&&a[tot]<0))a[tot]+=x;
            else a[++tot]=x;
        }
        for(int i=1;i<=tot;i++)if(a[i]>0){num++;ans+=a[i];}
        if(num<=m){cout<<ans;return 0;}
        m=num-m;int p=1;if(a[p]<0)p++;if(a[tot]<0)tot--;
        for(int i=p;i<=tot;i++)
        {
            if(a[i]<0)a[i]=-a[i];
            fro[i]=i-1;nex[i]=i+1;
            s.insert(node(i,a[i]));
        }
        fro[p]=0;nex[0]=p;nex[tot]=0;a[0]=10000000000000ll;
        while(m--)
        {
            int x=s.begin()->id;
            ans-=a[x];
            a[x]=-a[x];
            a[x]+=a[fro[x]];
            a[x]+=a[nex[x]];
            s.erase(s.begin());
            s.erase(node(fro[x],a[fro[x]]));
            s.erase(node(nex[x],a[nex[x]]));
            s.insert(node(x,a[x]));
            if(fro[fro[x]])nex[fro[fro[x]]]=x;
            if(nex[nex[x]])fro[nex[nex[x]]]=x;
            fro[x]=fro[fro[x]];
            nex[x]=nex[nex[x]];
        }
        cout<<ans;
    }
  • 相关阅读:
    域名解析成功但ping不通解决方案
    PHP如何通过rabbitMQ死信队列实现业务的延时/定时操作
    短视频自导自演,分镜脚本如何设计
    如何在uni-app中使用fingerprint2实现游客设备标识
    以PHP门面模式实现简单的邮件发送
    搜索接口优化方案——幂集分词表
    CUMTCTF'2020 未完成 wp
    CUMTCTF'2020 已做wp
    Sqli-labs 1-10
    ETCD组件在grpc中的实践
  • 原文地址:https://www.cnblogs.com/QTY2001/p/7632667.html
Copyright © 2011-2022 走看看