山海经(线段树)

山海经

题目描述

样例

输入

5 3
5 -6 3 -1 4
1 3
1 5
5 5

输出

1 1 5
3 5 6
5 5 4

题目大意

输入一个区间,求它所有子区间和的最大值。

题解

对于每一个区间 \(L~R\) 的最优解 \(i~j\) ,只有三种可能:

  • 一 全部在左子树中

  • 二 正好跨过中点,左子树右子树中都有一部分

  • 三 全部在右子树中

对于全部在子树中的情况,简单,直接递归查询。

难点在中间卡住的情况,不能找子区间再求和,那就直接从最优解出发,这个解就是一个区间和,由左右两部分组成,既然是最优解,那左右两部分一定也满足是最优,即左子树的最优后缀和和右子树的最优前缀和相加(也有可能是子树再向下递归时返回值)。

所以用线段树维护区间最优前缀和及端点,最优后缀和及端点,区间和,区间最优解,左右端点。

合并时前缀和为 左子树的前缀和 或 左子树的全部加上右子树的前缀和,后缀和同理,最优解合并见上文。

code
#include<bits/stdc++.h>
using namespace std;
#define ls (rt << 1)
#define rs (rt << 1 | 1)
#define lll long long
const int N = 100005;
const int M = (1e9);
int n,m,a[N];
int ww=-1;
struct T
{
	int l,r,data,qz,hz,q,h,ans,ansl,ansr;
}tr[N<<2];

T pushup(T rt1,T rt2)
{
	T tree;
	tree.data=rt1.data+rt2.data;
	tree.l=rt1.l; tree.r=rt2.r;
	if (rt1.q<rt1.data+rt2.q)
	{
		tree.q=rt1.data+rt2.q;
		tree.qz=rt2.qz;
	}
	else {tree.q=rt1.q; tree.qz=rt1.qz;}
	if (rt2.h<=rt2.data+rt1.h) 
	{
		tree.h=rt2.data+rt1.h; 
		tree.hz=rt1.hz;
	}
	else {tree.h=rt2.h; tree.hz=rt2.hz;}

	tree.ans=rt1.ans; 
	tree.ansl=rt1.ansl; 
	tree.ansr=rt1.ansr;//先选左边,附初始值。
	if(rt1.h+rt2.q>tree.ans)
	{
		tree.ans=rt1.h+rt2.q; 
		tree.ansl=rt1.hz; 
		tree.ansr=rt2.qz;
	}
	if(rt2.ans>tree.ans)
	{
		tree.ans=rt2.ans; 
		tree.ansl=rt2.ansl; 
		tree.ansr=rt2.ansr;
	}
	return tree;
}
void bui(int rt,int l,int r)
{
	tr[rt].l=l; tr[rt].r=r;
	if(l==r)
	{
		tr[rt].qz=tr[rt].hz=tr[rt].ansl=tr[rt].ansr=l;
		tr[rt].data=tr[rt].q=tr[rt].h=tr[rt].ans=a[l];
		return;
	}
	int mid=((lll)l+r)>>1;
	bui(ls,l,mid); 
	bui(rs,mid+1,r);
	tr[rt]=pushup(tr[ls],tr[rs]);
}
T que(int rt,int l,int r)
{
	if(l<=tr[rt].l&&r>=tr[rt].r) return tr[rt];
	int mid=((lll)tr[rt].l+tr[rt].r)>>1;
	if(r<=mid) 	return que(ls,l,r);
	else if(l>mid)	return que(rs,l,r);
	else return pushup(que(ls,l,r),que(rs,l,r));//中间情况,查找后合并。
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	bui(1,1,n);
	int x,y;
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d",&x,&y);
		T tree=que(1,x,y);
		printf("%d %d %d\n",tree.ansl,tree.ansr,tree.ans);
	}
	return 0;
}
posted @ 2024-02-21 16:09  ppllxx_9G  阅读(21)  评论(0编辑  收藏  举报