首页 > 其他分享 >最大子段和 - 题解

最大子段和 - 题解

时间:2024-07-29 23:28:06浏览次数:10  
标签:ch 最大 子段 int 题解 while include getchar

最大子段和

时间限制:C/C++ 1000MS,其他语言 2000MS
内存限制:C/C++ 128MB,其他语言 256MB

描述

给出一个长度为 \(n\) 的序列 \(a\),选出其中连续且非空的一段使得这段和最大。

输入描述

第一行是一个整数,表示序列的长度 \(n\)。
第二行有 \(n\) 个整数,第 \(i\) 个整数表示序列的第 \(i\) 个数字 \(a_i\)
\(1≤n≤2×10^5\),\(−10^4≤a_i≤10^4\)。

输出描述

输出一行一个整数表示答案。

用例输入 1

7
2 -4 3 -1 2 -4 3

用例输出 1

4

提示

【样例解释】

选取 \([3,5]\) 子段 \(3,−1,2\), 其和为 \(4\)

代码

贪心 做法

#include<cstdio>
#include<algorithm>
using namespace std;

inline int read()
{
	int x=0,w=1;char ch=getchar();
	while(ch<'0'||ch>'9')
	{
		if(ch=='-') w=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9')
	{
		x=(x<<3)+(x<<1)+(ch^'0');
		ch=getchar();
	}
	return x*w;
}

const int N=2e5+5,INF=0x3f3f3f3f;
int n,a[N],f[N];

int main()
{
	n=read();
	for(int i=1;i<=n;i++)
		a[i]=read();
	for(int i=1;i<=n;i++)
		f[i]=max(a[i],f[i-1]+a[i]);
	int ans=-INF;
	for(int i=1;i<=n;i++)
		ans=max(ans,f[i]);
	printf("%d\n",ans);
	return 0;
}

类线段树 做法

#include<cstdio>
#include<algorithm>
using namespace std;

inline int read()
{
	int x=0,w=1;char ch=getchar();
	while(ch<'0'||ch>'9')
	{
		if(ch=='-') w=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9')
	{
		x=(x<<3)+(x<<1)+(ch^'0');
		ch=getchar();
	}
	return x*w;
}

const int N=2e5+5;
int n,a[N];
struct RANGE{
	int l,r;
	int sum;
	int dat,ldat,rdat;
	void build(int il,int ir,int isumdat)
	{
		l=il,r=ir, sum=dat=ldat=rdat=isumdat;
		return;
	}
	void build(int il,int ir,int isum,int idat,int ildat,int irdat)
	{
		l=il,r=ir, sum=isum, dat=idat,ldat=ildat,rdat=irdat;
		return;
	}
};
RANGE rg[N<<2];

void div_conq(int p,int l,int r)
{
	if(l==r)
	{
		rg[p].build(l,r,a[l]);
		return;
	}
	int mid=(l+r)>>1;
	div_conq(p<<1,l,mid), div_conq((p<<1)+1,mid+1,r);
	rg[p].build(
		l,r,
		rg[p<<1].sum+rg[(p<<1)+1].sum,
		max(
			max(
				rg[p<<1].dat,
				rg[(p<<1)+1].dat
			),
			rg[p<<1].rdat+rg[(p<<1)+1].ldat
		),
		max(
			rg[p<<1].ldat,
			rg[p<<1].sum+rg[(p<<1)+1].ldat
		),
		max(
			rg[(p<<1)+1].rdat,
			rg[p<<1].rdat+rg[(p<<1)+1].sum
		)
	);
	return;
}

int main()
{
	n=read();
	for(int i=1;i<=n;i++)
		a[i]=read();
	div_conq(1,1,n);
	printf("%d\n",rg[1].dat);
	return 0;
}

标签:ch,最大,子段,int,题解,while,include,getchar
From: https://www.cnblogs.com/jerrycyx/p/18331293

相关文章

  • 数二数 题解
    我们定义\(f_i\)表示考虑\(n=i\)时的答案。考虑怎样才能使得Bob存在一种出题方案使得\(l\)与\(r\)无法确定。假设包含点\(i\)的询问集合为\(S_i\),那么当\(S_l=S_r\)时\(l\)与\(r\)无法确定。发现:如果\(a<b<c<d\),\(S_a=S_c\),\(S_b=S_d\),那么\(S_a=S_b=S_c=......
  • P8314 Parkovi 题解
    题意:树,边有边权,求一种选出\(k\)个点染色的方案,使得每个点到最近的一个被染色点的距离的最大值最小,\(n\le2\cdot10^5\).Solution先看部分分:\(n\le20\):直接\(C_n^k\)爆搜.\(k=1\):对每个点\(u\)求出\(f(u)\)和\(g(u)\)分别表示\(u\)到子树内点距离的最大值、\(u\)......
  • luogu P2371 [国家集训队] 墨墨的等式 题解
    luoguP2371[国家集训队]墨墨的等式题目传送门思路同余最短路同余最短路同余最短路与差分约束有异曲同工之妙,都将约束条件转化为边,每种状态转化为点。把本来与图论毫不相干的问题抽象到具体的图上,通过拓扑排序,最短路等基础算法获得最小状态,从而解决问题。在本题中,以\(0\)......
  • vue3中使用keepAlive缓存路由组件不生效的问题解决
    在Vue3中使用keep-alive缓存路由组件时,可能会遇到一些问题导致缓存不生效。以下是一些常见的问题及其解决方案:keep-alive写法错误:在Vue3中,使用keep-alive需要将router-view包裹在keep-alive中,并通过插槽传递组件。例如:<template><router-viewv-slot="{Co......
  • CF1523D Love-Hate 题解
    CF1523DLove-Hate题解传送门题目大意:给定\(m\)和\(n\)个集合,而且这\(n\)个集合的元素都是\(1\)~\(m\)中的数且没有重复,而且大小都不超过\(15\)。求一个最大的集合,使得这个集合是至少\(\left\lceil\frac{n}{2}\right\rceil\)个集合的子集。先想一个问题:题目是让......
  • CF1523E Crypto Lights 题解
    CF1523ECryptoLights题解传送门。题目大意:有\(n\)个台灯,初始时都是暗的,每次随机点亮一个暗台灯,若点亮后存在一个长度为\(k\)的连续段有大于一个台灯被点亮则立刻停止,求期望点亮多少台灯。(就是直接把原题翻译搬过来了)很明显的期望dp,状态定义也很明显,设\(f_i\)表示......
  • P8347 「Wdoi-6」另一侧的月 题解
    P8347「Wdoi-6」另一侧的月题解第一次自己思考出来紫题,题解纪念一下。下面为大家讲解如何一步步推到最终结论:首先,原树没有根,不妨设它的根为\(1\),将它转化成有根的,便于操作。为了方便描述,我们称将一个非根节点的点的父亲删去,保留含这个点的连通块这个操作为截取操作(就是......
  • CF538G Berserk Robot 题解
    Description有一个机器人,第\(0\)秒时在\((0,0)\)位置。机器人会循环执行一个长度为\(l\)的指令序列,每秒执行一个指令。指令有ULDR四种,分别代表向上/左/下/右移动一格。你不知道这个指令序列具体是什么,但是你知道\(n\)条信息,第\(i\)条信息为「第\(t_i\)秒时机器......
  • python找出字典中value最大值的几种方法
    假设定义一字典,m={"a":3,"e":6,"b":2,"g":7,"f":7,"c":1,"d":5},在不知道key的情况下如何找出字典中value最大的所有key-value对?下面讨论几种方法。1)通过m.values()和max()函数第一步,通过max()函数找到字典中的value最大值。max(m.values())结果为7第二步,再通......
  • CF1634F Fibonacci Additions 题解
    CF1634FFibonacciAdditions题解传送门。题目大意:给定两个序列\(A\)和\(B\),每次一个可以选一个区间,并在区间的第\(i\)个数加上\(F_i\),其中\(F\)是斐波那契数列,你需要在每次询问结束时输出两个序列是否相等。可以先求一个序列\(C\)表示\(A\)和\(B\)每个位置的......