zoukankan      html  css  js  c++  java
  • 51Nod 1052/1053/1115 最大M子段和V1/V2/V3

    V1

    N个整数组成的序列a[1],a[2],a[3],…,a[n],将这N个数划分为互不相交的M个子段,并且这M个子段的和是最大的。如果M >= N个数中正数的个数,那么输出所有正数的和。N,M<=5000
    例如:-2 11 -4 13 -5 -2,分为2段,11 -4 13一段,6一段,和为26。

    V2

    N个整数组成的序列a[1],a[2],a[3],…,a[n],将这N个数划分为互不相交的M个子段,并且这M个子段的和是最大的。如果M >= N个数中正数的个数,那么输出所有正数的和。 N,M<=50000
    例如:-2 11 -4 13 -5 6 -2,分为2段,11 -4 13一段,6一段,和为26。
    V3
    环形最大M子段和,N个整数组成的序列排成一个环,a[1],a[2],a[3],…,a[n]( a[n], a[1]也可以算作1段),将这N个数划分为互不相交的M个子段,并且这M个子段的和是最大的。如果M>=N个数中正数的个数,那么输出所有正数的和。N,M<=100000
    例如:-2 11 -4 13 -5 6 -1,分为2段,6 -1 -2 11一段,13一段,和为27。

    这三道题非常类似可以用几乎同一个code过掉

    我们直接先考虑V3比较好做

    首先将所有连续且符号相同的数加在一起,那么我们得到一个正负交替的环

    如果不考虑限制,显然取所有正数最优

    现在考虑限制,我们假设环上正数c个

    那么就要减少M-c段,考虑减少段数的手段

    1.删去一段

    2.将两端合并成为一段

    这个时候发现问题可以转化为经典的种花问题:

    将所有的正数变为负数,在N个数(全部为负)中选出M-c个最大的,而相邻的不能选

    选出来的数加上原本所有正数的和就是答案

    直接套用原来的可撤销贪心做法就可以了,v2就多加一个权值为-∞的0号节点即可

    V2code

    #pragma GCC opitmize("O3")
    #pragma G++ opitmize("O3")
    #include<queue>
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #define N 50010
    using namespace std;
    int n,m,t=0,l[N],r[N]; long long S=0,s[N],v[N];
    priority_queue<pair<long long,int> > q; bool vis[N]={0};
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;++i){
    		scanf("%lld",v+i);
    		if(!t && v[i]<0) continue; else
    		if(!t || (v[i]>=0)!=(s[t]>=0)) s[++t]=v[i]; else s[t]+=v[i];
    	}
    	while(s[t]<0) s[t--]=0;
    	for(int i=1;i<=t;++i){
    		l[i]=i-1; r[i]=i+1;
    		if(i&1){
    			S+=s[i]; s[i]=-s[i];
    			q.push(make_pair(s[i],i));
    		} else q.push(make_pair(s[i],i));
    	}
    	r[t]=0; l[0]=t; r[0]=1;
    	q.push(make_pair(s[0]=-1000000000000ll,0));
    	if(m>(t>>1)) return 0&printf("%lld
    ",S);
    	pair<long long,int> x; int y;
    	for(m=(t-(t>>1))-m;m--;){
    		x=q.top(); q.pop();
    		if(vis[y=x.second]){++m; continue;}
    		else{
    			S+=s[y]; s[y]=-s[y]+s[l[y]]+s[r[y]];
    			q.push(make_pair(s[y],y));
    			r[l[l[y]]]=y;
    			l[r[r[y]]]=y;
    			vis[l[y]]=1;
    			vis[r[y]]=1;
    			l[y]=l[l[y]];
    			r[y]=r[r[y]];
    		}
    	}
    	printf("%lld
    ",max(0ll,S));
    }
    V3code

    #pragma GCC opitmize("O3")
    #pragma G++ opitmize("O3")
    #include<queue>
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #define N 200010
    using namespace std;
    int n,m,t=0,l[N],r[N],c; long long S=0,s[N],v[N];
    priority_queue<pair<long long,int> > q; bool vis[N]={0};
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;++i){
    		scanf("%lld",v+i);
    		if(!t || (v[i]>=0)!=(s[t]>=0)) s[++t]=v[i]; else s[t]+=v[i];
    	}
    	if((s[1]>=0)==(s[t]>=0)) s[1]+=s[t--];
    	for(int i=1;i<=t;++i){
    		l[i]=i-1; r[i]=i+1;
    		if(s[i]>=0){
    			S+=s[i]; s[i]=-s[i]; c++;
    			q.push(make_pair(s[i],i));
    		} else q.push(make_pair(s[i],i));
    	}
    	r[t]=1; l[1]=t;
    	if(m>=c) return 0&printf("%lld
    ",S);
    	pair<long long,int> x; int y;
    	for(m=c-m;m--;){
    		x=q.top(); q.pop();
    		if(vis[y=x.second]){++m; continue;}
    		else{
    			S+=s[y]; s[y]=-s[y]+s[l[y]]+s[r[y]];
    			q.push(make_pair(s[y],y));
    			r[l[l[y]]]=y;
    			l[r[r[y]]]=y;
    			vis[l[y]]=1;
    			vis[r[y]]=1;
    			l[y]=l[l[y]];
    			r[y]=r[r[y]];
    		}
    	}
    	printf("%lld
    ",max(0ll,S));
    }


  • 相关阅读:
    Log4net快速搭建
    WebAPI中Area的使用
    (三)Redis for StackExchange.Redis
    (二)Redis for 阿里云公网连接
    Python+CGI,在Windows上快速部署Python到IIS
    腾讯云
    UIView添加事件
    Sublime Text Packages Control 安装
    乎乎测试
    常用第三方类库
  • 原文地址:https://www.cnblogs.com/Extended-Ash/p/8511192.html
Copyright © 2011-2022 走看看