zoukankan      html  css  js  c++  java
  • 51nod 最大M子段和系列

    1052 最大M子段和

    N个整数组成的序列a[1],a[2],a[3],…,a[n],将这N个数划分为互不相交的M个子段,并且这M个子段的和是最大的。如果M >= N个数中正数的个数,那么输出所有正数的和。
    例如:-2 11 -4 13 -5 6 -2,分为2段,11 -4 13一段,6一段,和为26。
    Input
    第1行:2个数N和M,中间用空格分隔。N为整数的个数,M为划分为多少段。(2 <= N , M <= 5000)
    第2 - N+1行:N个整数 (-10^9 <= a[i] <= 10^9)
    Output
    输出这个最大和
    Input示例
    7 2
    -2
    11
    -4
    13
    -5
    6
    -2
    Output示例
    26
    ———————————————————————————————————
    1254 最大子段和 V2
    N个整数组成的序列a[1],a[2],a[3],…,a[n],你可以对数组中的一对元素进行交换,并且交换后求a[1]至a[n]的最大子段和,所能得到的结果是所有交换中最大的。当所给的整数均为负数时和为0。
    例如:{-2,11,-4,13,-5,-2, 4}将 -4 和 4 交换,{-2,11,4,13,-5,-2, -4},最大子段和为11 + 4 + 13 = 28。
     
    Input
    第1行:整数序列的长度N(2 <= N <= 50000)
    第2 - N + 1行:N个整数(-10^9 <= A[i] <= 10^9)
    Output
    输出交换一次后的最大子段和。
    Input示例
    7
    -2
    11
    -4
    13
    -5
    -2
    4
    Output示例
    28
    ——————————————————————————
    因为这两道题是一种写法所以我就写在一起
    就把连续的一段正负的合在一起得到一段正负相间的序列
    然后记录一共有多少个正的记为tot 题目要保留的段数记为 k
    那么我们就需要消掉tot-k份 消掉的方法有放弃某一段正的或者是用一段负的把两段正的合并
    这样我们维护一个堆 权值是需要付出的代价 这样慢慢合并就能解决问题了
    记得记录每一段的相邻段就好辣 当然记得特判边界 我的处理方法是加一段权值为负无穷的段就好辣
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #define LL long long
    using namespace std;
    const int M=1e6+1e5+7;
    const LL inf=1e15;
    LL read(){
        LL ans=0,f=1,c=getchar();
        while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();}
        return ans*f;
    }
    int n,k,f[M],lx[M],rx[M];
    LL cnt,sum[M],v,ans;
    bool pd(LL x,LL y){return !x||!y||(x>0)==(y>0);}
    LL pabs(LL x){return x>=0?x:-x;}
    struct node{
        LL w,pos;
        bool operator <(const node& x)const{return x.w<w;}
    };
    priority_queue<node>q;
    int main(){
        n=read(); k=read();
        int h=1; 
        while(h<=n&&(v=read())<=0) h++;//printf("[%d]
    ",h);
        if(v>0) sum[++cnt]=v;
        for(int i=h+1;i<=n;i++){
            v=read();
            if(pd(sum[cnt],v)) sum[cnt]+=v;
            else sum[++cnt]=v;
        }
        if(pd(sum[cnt],-inf)) sum[cnt]+=-inf;
        else sum[++cnt]=-inf;
        int tot=0; for(int i=1;i<=cnt;i++)if(sum[i]>=0) ans+=sum[i],tot++;
        if(tot<=k) return printf("%lld
    ",ans),0;
        int now=tot-k;
        for(int i=1;i<=cnt;i++) q.push((node){pabs(sum[i]),i}),lx[i]=i-1,rx[i]=i+1;
        lx[1]=cnt; rx[cnt]=1;
        while(now){
            node x=q.top(); q.pop();
            int k=x.pos;
            if(f[k]) continue;
            ans-=x.w; now--;
            LL l=lx[k],r=rx[k];
            f[l]=1; f[r]=1;
            sum[++cnt]=sum[k]+sum[l]+sum[r];
            q.push((node){pabs(sum[cnt]),cnt});
            lx[cnt]=lx[l]; rx[cnt]=rx[r];
            rx[lx[l]]=cnt; lx[rx[r]]=cnt;  
        }
        printf("%lld
    ",ans);
        return 0;
    }
    View Code

    1115 最大M子段和 V3

    环形最大M子段和,N个整数组成的序列排成一个环,a[1],a[2],a[3],…,a[n](a[n-1], a[n], a[1]也可以算作1段),将这N个数划分为互不相交的M个子段,并且这M个子段的和是最大的。如果M >= N个数中正数的个数,那么输出所有正数的和。
    例如:-2 11 -4 13 -5 6 -1,分为2段,6 -1 -2 11一段,13一段,和为27。
     
    Input
    第1行:2个数N和M,中间用空格分隔。N为整数的个数,M为划分为多少段。(2 <= N , M <= 100000)
    第2 - N+1行:N个整数 (-10^9 <= a[i] <= 10^9)
    Output
    输出这个最大和
    Input示例
    7 2
    -2
    11
    -4
    13
    -5
    6
    -2
    Output示例
    26
    ————————————————————————
    这道题不需要特判边界反而更容易QAQ
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<cmath>
    #include<cstdlib>
    #define LL long long
    using namespace std;
    const int M=1500007;
    LL read(){
        LL ans=0,f=1,c=getchar();
        while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();}
        return ans*f;
    }
    LL lx[M],rx[M],w[M];
    LL n,k,tot;
    LL cnt=1;
    LL sum[M],ans;
    bool f[M];
    struct node{
        LL w,pos;
        bool operator<(const node &x) const{return w>x.w;}
    };
    priority_queue<node>q;
    LL pd(LL x){return x>=0?x:-x;}
    bool okay(LL a,LL b){return (a<0&&b<0)||(a>0&&b>0)||!a||!b;}
    int main()
    {
        LL v;
        n=read(); k=read();
        for(int i=1;i<=n;i++){
            v=read();
            if(okay(sum[cnt],v)) sum[cnt]+=v;
            else sum[++cnt]=v;
        }
        if(okay(sum[1],sum[cnt])) sum[1]=sum[cnt]+sum[1],cnt--;
        for(int i=1;i<=cnt;i++) 
            if(sum[i]>0) ans+=sum[i],tot++; 
        if(tot<=k){printf("%lld
    ",ans); return 0;}
        LL now=tot-k;
        q.push((node){pd(sum[1]),1}); 
        lx[1]=cnt; rx[1]=2; w[1]=pd(sum[1]);
        q.push((node){pd(sum[cnt]),cnt});
        lx[cnt]=cnt-1; rx[cnt]=1; w[cnt]=pd(sum[cnt]);
        for(int i=2;i<cnt;i++)  
            q.push((node){pd(sum[i]),i}),lx[i]=i-1,rx[i]=i+1,w[i]=pd(sum[i]);
        while(now){
            node x=q.top(); q.pop();
            LL k=x.pos;
            if(f[k]) continue;
            ans-=w[k]; now--;
            LL l=lx[k],r=rx[k];
            f[l]=1; f[r]=1;
            cnt++;
            sum[cnt]=sum[k]+sum[l]+sum[r];
            w[cnt]=pd(sum[cnt]);
            q.push((node){w[cnt],cnt});
            lx[cnt]=lx[l]; rx[cnt]=rx[r];
            rx[lx[l]]=cnt; lx[rx[r]]=cnt;  
        }
        printf("%lld
    ",ans);
        return 0;
    }
    View Code
    
    
    
     
  • 相关阅读:
    使用pycharm专业版(支持远程调试及运行)如何运行mpi的代码呢???(mpi4py的代码)
    使用MPI时执行代码时运行命令中参见的几种参数设置
    多网卡系统下如何使用tcp协议实现MPI的分布式多机运行(mpi的实现使用openmpi)
    为什么我要弃用华为的软件产品——mindspore从入门到放弃之感想
    网络文件系统nfs服务端配置客户端权限时的demo例子
    【转载】 NFS服务器端的权限设置学习 Linux运维学习
    Ubuntu18.04系统下网络文件系统nfs的安装及简单配置
    【转载】 Sun RPC 编程简介
    【转载】 SUN RPC的传输层实现机制 —— rpcbind(nfs文件系统中的rpc)
    【转载】sun的rpc ——rpcbind(nfs文件系统中的rpc)
  • 原文地址:https://www.cnblogs.com/lyzuikeai/p/7443289.html
Copyright © 2011-2022 走看看