[线段树]校OJ-Can you answer on these queries III

Posted zero_orez6

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[线段树]校OJ-Can you answer on these queries III相关的知识,希望对你有一定的参考价值。

Can you answer on these queries III

题目简述

给定长度为N的数列A,以及M条指令 ( N ≤ 500000 , M ≤ 100000 ) (N≤500000, M≤100000) (N500000,M100000),每条指令可能是以下两种之一:

“2 x y”,把 A[x] 改成 y。

“1 x y”,查询区间 [x,y] 中的最大连续子段和,即区间 [ l , r ] [l,r] [l,r]内,连续累加和最大的。 对于每个询问,输出一个整数表示答案。

//input
5 3
1 2 -3 4 5
1 2 3
2 2 -1
1 3 2
//output
2
-1

思路
线段树的整体思路不变,我们只需在建树和单点修改时变化一下从下往上传递的信息即可,多维护三个信息,即连续最大子段和dat,左端的连续最大子段和lmax,以及右端的连续最大子段和rmax

t[bh].sum=t[bh*2].sum+t[bh*2+1].sum;
t[bh].lmax=max(t[bh*2].lmax,t[bh*2+1].lmax+t[2*bh].sum);
t[bh].rmax=max(t[bh*2+1].rmax,t[bh*2].rmax+t[2*bh+1].sum);
t[bh].dat=max(t[bh*2].dat,max(t[bh*2+1].dat,t[bh*2].rmax+t[bh*2+1].lmax));

PS:1.这里建议写一个更新函数update(int bh),每次更新值时调用次函数即可
2.线段树一般有多组输入输出,建议用快读或 s c a n f , p r i n t f scanf,printf scanf,printf

void update(int bh)
{
	t[bh].sum=t[bh*2].sum+t[bh*2+1].sum;
	t[bh].lmax=max(t[bh*2].lmax,t[bh*2+1].lmax+t[2*bh].sum);
	t[bh].rmax=max(t[bh*2+1].rmax,t[bh*2].rmax+t[2*bh+1].sum);
	t[bh].dat=max(t[bh*2].dat,max(t[bh*2+1].dat,t[bh*2].rmax+t[bh*2+1].lmax));
}

code

#include <bits/stdc++.h>
using namespace std;
const int MAXN=500086;
struct tree{
	int l,r,lmax,sum,rmax,dat;
}t[4*MAXN];
int n,a[MAXN],m;
void update(int bh)
{
	t[bh].sum=t[bh*2].sum+t[bh*2+1].sum;
	t[bh].lmax=max(t[bh*2].lmax,t[bh*2+1].lmax+t[2*bh].sum);
	t[bh].rmax=max(t[bh*2+1].rmax,t[bh*2].rmax+t[2*bh+1].sum);
	t[bh].dat=max(t[bh*2].dat,max(t[bh*2+1].dat,t[bh*2].rmax+t[bh*2+1].lmax));
} 
void build(int bh,int l,int r)
{
	t[bh].l=l;	
	t[bh].r=r;	
	if(l==r)
	{
		t[bh].sum=a[l];
		t[bh].dat=a[l];
		t[bh].lmax=a[l];
		t[bh].rmax=a[l];
		return ;
	}
	int mid=(l+r)/2;
	build(2*bh,l,mid);
	build(2*bh+1,mid+1,r);
	update(bh);
}
void change(int bh,int x,int summ)
{
	
	if(t[bh].l==t[bh].r)
	{
		t[bh].sum=summ;
		t[bh].dat=summ;
		t[bh].lmax=summ;
		t[bh].rmax=summ;
		return ;
	}
	int mid=(t[bh].l+t[bh].r)/2;
	if(x<=mid) change(bh*2,x,summ);
	else change(bh*2+1,x,summ);
	update(bh);
}
tree ask(int bh,int l,int r)
{
	if(l<=t[bh].l&&r>=t[bh].r)
	{
		return t[bh];
	}
	int mid=(t[bh].l+t[bh].r)/2;
	int w=-MAXN*10;
	if(mid>=r) return ask(bh*2,l,r);
	if(mid<l) return ask(bh*2+1,l,r);
	else {
		tree ans,left,right;
        left=ask(bh*2,l,r);
        right=ask(bh*2+1,l,r);
        ans.sum=left.sum+right.sum;
        ans.dat=max(max(left.dat,left.rmax+right.lmax),right.dat);
        ans.lmax=max(left.lmax,left.sum+right.lmax);
        ans.rmax=max(right.rmax,right.sum+left.rmax);
        return ans;
	}
}
int main()
{
	freopen("b.in","r",stdin);
	freopen("b.out","w",stdout);
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
	}
	build(1,1,n);
	int a,b,c;
	while(m--)
	{
		scanf("%d%d%d",&a,&b,&c);
		if(a==2) change(1,b,c);
		else 
		{
			if(b>c) swap(b,c);
			printf("%d\\n",ask(1,b,c).dat);	
		}
	}
    return 0;
}

以上是关于[线段树]校OJ-Can you answer on these queries III的主要内容,如果未能解决你的问题,请参考以下文章

HDU 4027 Can you answer these queries? (线段树)

HDU 4027 Can you answer these queries?(线段树)

HDU4027 Can you answer these queries? —— 线段树 区间修改

HDU-Can you answer these queries? (线段树+区间修改)

GSS1 - Can you answer these queries I(线段树)

HDU 4027 Can you answer these queries?(线段树区间开方)