1. 程式人生 > 實用技巧 >【線段樹】序列問題/Can you answer on these queries III

【線段樹】序列問題/Can you answer on these queries III

Description

給定長度為N的數列A,以及M條指令,每條指令可能是以下兩種之一:

1、“1 x y”,查詢區間 [x,y] 中的最大連續子段和。

2、“2 x y”,把 A[x] 改成 y。對於每個查詢指令,輸出一個整數表示答案。

Input

第一行兩個整數N,M。

第二行N個整數A[i]。

接下來M行每行3個整數k,x,y,k=1表示查詢(此時如果x>y,請交換x,y),k=2表示修改。

資料範圍

N ≤ 500000,M ≤ 100000

Output

對於每個查詢指令輸出一個整數表示答案。

每個答案佔一行。

Sample Input

5 3
1 2 -3 4 5
1 2 3
2 2 -1
1 3 2

Sample Output

2
-1


思路

  • 線段樹維護:區間緊靠左右兩端的最大連續子段和,區間的總和,區間跨左右子樹的最大連續子段和
  • 當前區間的lmax=左子樹lmax和或左子樹區間和+右子樹lmax(rmax同理)
  • 極小值-inf注意不能過小,溢位坑死人

程式碼

#include <iostream>
#include <cstdio>
#define maxn 500005
#define inf 1005
using namespace std;
int n,m,v[maxn];
struct fdfdfd{int l,r,lmax,rmax,amax,sum;}a[maxn<<2];
void pushup(int x)
{
	a[x].sum=a[x<<1].sum+a[x<<1|1].sum;
	a[x].lmax=max(a[x<<1].lmax,a[x<<1].sum+a[x<<1|1].lmax);
	a[x].rmax=max(a[x<<1|1].rmax,a[x<<1|1].sum+a[x<<1].rmax);
	a[x].amax=max(max(a[x<<1].amax,a[x<<1|1].amax),a[x<<1].rmax+a[x<<1|1].lmax);
}
void build(int x,int left,int right)
{
	a[x].l=left; a[x].r=right;
	if(left==right)
	{
		a[x].lmax=a[x].rmax=a[x].amax=a[x].sum=v[left];
		return;
	}
	int mid=(left+right)>>1;
	build(x<<1,left,mid); build(x<<1|1,mid+1,right);
	pushup(x);
}
void modify(int x,int u,int d)
{
	if(a[x].r<u||a[x].l>u) return;
	if(a[x].l==u&&a[x].r==u)
	{
		a[x].lmax=a[x].rmax=a[x].amax=a[x].sum=d;
		return;
	}
	modify(x<<1,u,d); modify(x<<1|1,u,d);
	pushup(x);
}
fdfdfd query(int x,int left,int right)
{
	if(a[x].r<left||a[x].l>right) return (fdfdfd){0,0,-inf,-inf,-inf,-inf};
	if(left<=a[x].l&&right>=a[x].r) return a[x];
	fdfdfd temp1=query(x<<1,left,right),temp2=query(x<<1|1,left,right),temp;
	temp.sum=temp1.sum+temp2.sum;
	temp.lmax=max(temp1.lmax,temp1.sum+temp2.lmax);
	temp.rmax=max(temp2.rmax,temp2.sum+temp1.rmax);
	temp.amax=max(max(temp1.amax,temp2.amax),temp1.rmax+temp2.lmax);
	return temp;
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i) scanf("%d",&v[i]);
	build(1,1,n);
	while(m--)
	{
		int f1,f2,f3; scanf("%d%d%d",&f1,&f2,&f3);
		if(f1==1)
		{
			if(f2>f3) swap(f2,f3);
			printf("%d\n",query(1,f2,f3).amax);
		}
		else modify(1,f2,f3);
	}
	return 0;
}