1. 程式人生 > >洛谷4513 小白逛公園(線段樹)

洛谷4513 小白逛公園(線段樹)

【題目分析】

題意。。。很明顯看出要維護區間子序列最大值,那麼問題就在於如何在區間合併的時候更新區間子序列最大值。

可以推出,區間子序列最大值要麼是從最左邊開始的一段,要麼是最右邊向左的一段,要麼是中間的一段,對於第一種,我們發現要麼是左兒子最左邊的一段,要麼是左兒子+右兒子左邊一段,第二種同理。

對於第三種,要麼是左兒子的最大值,要麼是右兒子的最大值,要麼是左兒子的右邊的一段與右兒子的左邊的一段拼起來。

然後就over啦

【程式碼~】

#include<bits/stdc++.h>
using namespace std;
const int MAXN=5e5+10;

struct Tree{
	int l,r;
	int ls,rs,maxs;
	int sum;
}tr[MAXN<<2];

int n,m;
int scor[MAXN];

void push_up(int root)
{
	tr[root].sum=tr[root<<1].sum+tr[root<<1|1].sum;
	tr[root].ls=max(tr[root<<1].ls,tr[root<<1].sum+tr[root<<1|1].ls);
	tr[root].rs=max(tr[root<<1|1].rs,tr[root<<1|1].sum+tr[root<<1].rs);
	tr[root].maxs=max(max(tr[root<<1].maxs,tr[root<<1|1].maxs),tr[root<<1].rs+tr[root<<1|1].ls);
}

void build(int root,int l,int r)
{
	tr[root].l=l;
	tr[root].r=r;
	if(l==r)
	{
		tr[root].ls=tr[root].rs=tr[root].maxs=tr[root].sum=scor[l];
		return ;
	}
	int mid=l+r>>1;
	build(root<<1,l,mid);
	build(root<<1|1,mid+1,r);
	push_up(root);
}

void update(int root,int l,int r,int x,int key)
{
	if(l==r)
	{
		tr[root].ls=tr[root].rs=tr[root].maxs=tr[root].sum=key;
		return ;
	}
	int mid=l+r>>1;
	if(x<=mid)
	  update(root<<1,l,mid,x,key);
	else
	  update(root<<1|1,mid+1,r,x,key);
	push_up(root);
}

Tree query(int root,int L,int R)
{
	if(L<=tr[root].l&&tr[root].r<=R)
	  return tr[root];
	int mid=tr[root].l+tr[root].r>>1;
	if(R<=mid)
	  return query(root<<1,L,R);
	if(L>mid)
	  return query(root<<1|1,L,R);
	Tree ans,ans1=query(root<<1,L,mid),ans2=query(root<<1|1,mid+1,R);
	ans.l=ans1.l,ans.r=ans2.r;
	ans.ls=max(ans1.ls,ans1.sum+ans2.ls);
	ans.rs=max(ans2.rs,ans2.sum+ans1.rs);
	ans.maxs=max(max(ans1.maxs,ans2.maxs),ans1.rs+ans2.ls);
	ans.sum=ans1.sum+ans2.sum;
	return ans;
}

int Read()
{
	int i=0,f=1;
	char c;
	for(c=getchar();(c>'9'||c<'0')&&c!='-';c=getchar());
	if(c=='-')
	  f=-1,c=getchar();
	for(;c>='0'&&c<='9';c=getchar())
	  i=(i<<3)+(i<<1)+c-'0';
	return i*f;
}

int main()
{
	n=Read(),m=Read();
	for(int i=1;i<=n;++i)
	  scor[i]=Read();
	build(1,1,n);
	while(m--)
	{
		int cz=Read(),l=Read(),r=Read();
		if(cz==1)
		{
			if(l>r)
			  swap(l,r);
			printf("%d\n",query(1,l,r).maxs);
		}
		else
		  update(1,1,n,l,r);
	}
	return 0;
}