版权声明:请大家斧正,如喜欢的话,为拙见点一个赞吧。 https://blog.csdn.net/qq_39897867/article/details/81949585
题目
https://www.luogu.org/problemnew/show/SP1716
解题思路
在线段树上的每个节点上,除了区间端点外,在维护4个信息:区间和 ,区间最大连续字段和 ,紧靠左端的最大连续字段和 ,紧靠右端的最大连续字段和 。
在线段树的正常模板下处理一下即可(不过我因为交换打错了, 了很久!!!)->
代码
#include<cstdio>
using namespace std;
struct node{int sum,lmax,rmax,dat;}a[2000501];
int n,m,x,y,t,b[500010];
int max(int x,int y){ return x>y?x:y;}
void caa(int k){
a[k].sum=a[k*2].sum+a[k*2+1].sum;
a[k].lmax=max(a[k*2].lmax,a[k*2].sum+a[k*2+1].lmax);
a[k].rmax=max(a[k*2+1].rmax,a[k*2+1].sum+a[k*2].rmax);
a[k].dat=max(max(a[k*2].dat,a[k*2+1].dat),a[k*2].rmax+a[k*2+1].lmax);
}
void build(int k,int l,int r){
if (l==r) {a[k]=(node){b[l],b[l],b[l],b[l]}; return;}
int mid=(l+r)/2;
build(k*2,l,mid);
build(k*2+1,mid+1,r);
caa(k);
}
node ask(int k,int l,int r,int x,int y){
if (l==x&&r==y) return a[k];
int mid=(l+r)/2;
if (y<=mid) return ask(k*2,l,mid,x,y);
else if (x>mid) return ask(k*2+1,mid+1,r,x,y);
else {
node xx=ask(k*2,l,mid,x,mid);
node yy=ask(k*2+1,mid+1,r,mid+1,y);
node q;
q.sum=xx.sum+yy.sum;
q.lmax=max(xx.lmax,xx.sum+yy.lmax);
q.rmax=max(yy.rmax,yy.sum+xx.rmax);
q.dat=max(max(xx.dat,yy.dat),xx.rmax+yy.lmax);
return q;
}
}
void change(int k,int l,int r,int x,int y){
if (l==r) {a[k]=(node){y,y,y,y}; return;}
int mid=(l+r)/2;
if (x<=mid) change(k*2,l,mid,x,y);
else change(k*2+1,mid+1,r,x,y);
caa(k);
}
int main()
{
scanf("%d",&n); scanf("%d",&m);
for (int i=1;i<=n;i++) scanf("%d",&b[i]);
build(1,1,n);
while (m--){
scanf("%d%d%d",&t,&x,&y);
if (t==1){
if (x>y) {int g=x; x=y; y=g;}
printf("%d\n",ask(1,1,n,x,y).dat);
} else change(1,1,n,x,y);
}
}