首页 > 其他分享 >51nod 最大M子段和v1/v2/v3

51nod 最大M子段和v1/v2/v3

时间:2024-09-10 09:14:18浏览次数:1  
标签:11 const 子段 51nod ll 个数 v1 int 正数

学习笔记

最大M子段和 V1

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

最大M子段和 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\)。

v2 是 v1 的升级版,而v3是v2的特殊版(更好处理了)所以我们先讲v2,我们将连续的正数和连续的负数都连成一段,对每个段用链表储存,对每一段的值用优先队列储存绝对值,对于绝对值小的段考虑将他两边的段合并,更新值。

看代码好理解,文字真的没啥意思。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=5e4+5;
int n,m;
int a[N];//原值 
int k;//总段数 
int p;//正数段数  
ll s;//正数和 
ll ans;//总答案 
ll c[N];
int l[N],r[N];//左右的段的编号 
int tra[N];//标记是否被合并 

struct cmp{
	bool operator()(const int x,const int y){
		return abs(c[x])>abs(c[y]);//绝对值排序 
	}
};
priority_queue<int,vector<int>,cmp> q;
int main(){
	ios::sync_with_stdio(false);
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	for(int i=1;i<=n;i++){
		if((ll)a[i]*a[i-1]<0){//异号 
			if(s>0){//是正数要储存答案 
				ans+=s;//先求正数总和 
				++p;//正数段数增加 
			}
			c[++k]=s;//开新段 
			s=a[i];//段正常增加 
		}
		else{
			s+=a[i];//同号增加增加 
		}
	}
	if(s>0){//因为边界 
		ans+=s;//累加 
		p++;//正数段数增加 
	}
	if(s){
		c[++k]=s;//非零新开一段 
	}
	//链表操作 
	r[1]=2;
	q.push(1);
	for(int i=2;i<k;i++){
		l[i]=i-1;
		r[i]=i+1;
		q.push(i);
	} 
	l[k]=k-1;
	q.push(k);
	int le=p-m;//需要合并几个段 
	if(le<=0){//已经可以输出了 
		cout<<ans;
		return 0;
	}
	int now;
	while(1){
		now=q.top();
		q.pop();
		if(tra[now]){
			continue;
		}
		if(c[now]<=0&&(!l[now]||!r[now])){//负数且在最左和最右 
			continue;
		}
		ans-=abs(c[now]);//合并了减去 
		c[now]+=c[l[now]]+c[r[now]];//合并值 
		if(l[now]){//能左合并 
			tra[l[now]]=1;
			l[now]=l[l[now]];
			r[l[now]]=now;
		}
		if(r[now]){//能右合并 
			tra[r[now]]=1;
			r[now]=r[r[now]];
			l[r[now]]=now;
		}
		q.push(now);
		le--;//减少合并次数 
		if(!le){
			break;
		}
	}
	cout<<ans;
	return 0;
} 

看懂上面了,v3 直接就知道怎么操作,无非就是链表上进行操作。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e5+5;
int n,m;
int a[N];
int k;
int p;
ll s;
ll ans;
ll c[N];
int l[N],r[N];
int tra[N];

struct cmp{
	bool operator()(const int x,const int y){
		return abs(c[x])>abs(c[y]);
	}
};

priority_queue<int,vector<int>,cmp> q;

int main(){
	ios::sync_with_stdio(false);
	
	cin>>n>>m;
	
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	
	for(int i=1;i<=n;i++){
		if((ll)a[i]*a[i-1]<0){
			if(s>0){
				ans+=s;
				++p;
			}
			c[++k]=s;
			s=a[i];
		}
		else{
			s+=a[i];
		}
	}
	if(s>0){
		ans+=s;
		if(c[1]<0){//无法首尾合并 
			++p;
		} 
	}
	
	if(s){
		if(c[1]*s<0){//无法首尾合并 
			c[++k]=s;
		}
		else{
			c[1]+=s;//能合并 
		}
	}
	//这注意改 
	l[1]=k;
	r[1]=2;
	q.push(1);
	for(int i=2;i<k;i++){
		l[i]=i-1;
		r[i]=i+1;
		q.push(i);
	} 
	l[k]=k-1;
	r[k]=1;
	q.push(k);
	
	int le=p-m;
	
	if(le<=0){
		cout<<ans;
		return 0;
	}
	int now;
	while(1){
		now=q.top();
		q.pop();
		if(tra[now]){
			continue;
		}
		
		if(c[now]<=0&&(!l[now]||!r[now])){
			continue;
		}
		
		ans-=abs(c[now]);
		
		c[now]+=c[l[now]]+c[r[now]];
		//直接合并 
		tra[l[now]]=1;
		l[now]=l[l[now]];
		r[l[now]]=now;
		
		tra[r[now]]=1;
		r[now]=r[r[now]];
		l[r[now]]=now;
		
		q.push(now);
		le--;
		if(!le){
			break;
		}
	}
	
	cout<<ans;
	
	return 0;
} 

标签:11,const,子段,51nod,ll,个数,v1,int,正数
From: https://www.cnblogs.com/sadlin/p/18405774

相关文章

  • MapBox Android版开发 4 国际化功能v11
    MapBoxAndroid版开发4国际化功能v11前言遇到的问题国际化功能原文给出的方案(V10版)migrate-to-v11适用于V11版的代码示例MapStyle类运行效果图前言在前文MapBox地图样式v11中,使用Style的localizeLabels方法本地化地图语言。但MapboxStandard样式和MapboxStan......
  • 经销商订货管理系统V1.0.1
    订货管理系统适用于经销商订货、连锁加盟门店订货、批发贸易订货等。为连锁型品牌、商贸批发类或工厂企业客户提供支持业务模式的分成数字化营销方案。提供前后端无加密源码,独立部署,不受限制。V1.0.1增加差价分成1、增加差价分成2、增加再次订购3、其他优化......
  • AJAX家政系统V1.0.1
    原生微信小程序开发的一款同城预约、上门服务、到店核销家政系统,用户端、服务端(高级授权)、门店端(高级授权)各端相互依赖又相互独立,支持选择项目、选择服务人员、选择门店多种下单方式,支持上门服务和到店核销两种服务方式,支持自营和多商家联营(高级授权)两种运营模式,同时支持多城......
  • 沃德校友会管理系统V1.0.1
    校友会综合服务平台,即校友信息管理平台、活动管理平台、校友服务大厅、校友企业服务平台等,实现集中学校、学院、校友会于一体的基础服务平台的搭建,建设一个满足校友信息化长期发展的、可扩展的综合校友服务平台,提供全部无加密源代码,支持私有化部署。目前Uniapp仅支持编译微信小程序......
  • 企业网站管理系统(多语言)V1.3.2
    企业网站管理系统,支持自定义多语言、自定义模型与字段、自定义表单等功能。提供全部无加密源代码,支持私有化部署。V1.3.2切换语言后获取配置错误的问题优化:2024模板若干问题优化:上一页、下一页标签增加order排序属性修复:重要切换语言后获取配置错误的问题(建议升级)修复:后台api翻译功......
  • 51nod 1051 最大子矩阵和
    51nod1051最大子矩阵和可以用前缀和容斥优化到\(O(n^4)\),但是不够进行如下图操作:将每一列的数值都压缩到一维的数组上,就转换为求最大字段和问题,时间复杂度\(O(n^3)\)。看看代码就知道了。#include<bits/stdc++.h>usingnamespacestd;#definelllonglongintn,m;......
  • 51nod 1243 排船的问题
    51nod1243排船的问题求最长绳子最短,考虑二分答案,判断时我们优先向左放,看是否能全放下。#include<bits/stdc++.h>usingnamespacestd;#definelllonglongintn,x,m;intpos[50005];intcheck(intmid){ intp=x;//偏差地图 intx2=x*2; intmx=m+x;//偏差地图 ......
  • AJAX家政系统V1.0.1
    一款同城预约、上门服务、到店核销家政系统,用户端、服务端(高级授权)、门店端(高级授权)各端相互依赖又相互独立,支持选择项目、选择服务人员、选择门店多种下单方式,支持上门服务和到店核销两种服务方式,支持自营和多商家联营(高级授权)两种运营模式,同时支持多城市并且设置每个城......
  • YOLOv10改进:CA注意力机制【注意力系列篇】(附详细的修改步骤,以及代码,目标检测效果优于
    YOLOv10改进:CA注意力机制【注意力系列篇】(附详细的修改步骤,以及代码)如果实验环境尚未搭建成功,可以参考这篇文章->【YOLOv10超详细环境搭建以及模型训练(GPU版本)】文章链接为:http://t.csdnimg.cn/YQ9qW--------------------------------------------------------------------......
  • 51nod 1020 逆序排列
    51nod1020逆序排列学习笔记其实要预处理,但唐的我非要每次都求一遍。设状态为\(dp[i][j]\)选了i个数逆序对数为j的排序种类数。首先初始化\(dp[i][0]=1\)即没有逆序对,转移方程\(dp[i][j]=dp[i-1][j]+dp[i-1][j-1]+……+dp[i-1][j-i]\)这是显然的(放上这个数,会产生的......