题目
题意:求区间最大连续子段和,有单点修改
Solution
s
u
m
sum
sum表示区间和,
l
l
l表示包含左端点的最大连续子段和,
r
r
r表示包含右端点的最大连续子段和,
a
l
l
all
all表示整个区间的最大连续子段和
#include<bits/stdc++.h>
using namespace std;
const int N=500002;
#define mid ((l+r)>>1)
struct node{
int sum,l,r,all;
}tr[N<<2];
int n,m,x,y,op;
inline char gc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int rd(){
int x=0,fl=1;char ch=gc();
for (;ch<48||ch>57;ch=gc())if(ch=='-')fl=-1;
for (;48<=ch&&ch<=57;ch=gc())x=(x<<3)+(x<<1)+(ch^48);
return x*fl;
}
inline void wri(int a){if(a>=10)wri(a/10);putchar(a%10|48);}
inline void wln(int a){if(a<0)a=-a,putchar('-');wri(a),puts("");}
node operator +(node le,node ri){
return (node){le.sum+ri.sum,max(le.l,le.sum+ri.l),max(ri.r,le.r+ri.sum),max(max(le.all,ri.all),le.r+ri.l)};
}
void build(int t,int l,int r){
if (l==r){
x=rd();
tr[t]=(node){x,x,x,x};
return;
}
build(t<<1,l,mid);
build(t<<1|1,mid+1,r);
tr[t]=tr[t<<1]+tr[t<<1|1];
}
node query(int t,int l,int r,int x,int y){
if (x==l && r==y) return tr[t];
if (y<=mid) return query(t<<1,l,mid,x,y);
if (x>mid) return query(t<<1|1,mid+1,r,x,y);
return query(t<<1,l,mid,x,mid)+query(t<<1|1,mid+1,r,mid+1,y);
}
void update(int t,int l,int r,int x,int v){
if (l==r){
tr[t]=(node){v,v,v,v};
return;
}
if (x<=mid) update(t<<1,l,mid,x,y);
else update(t<<1|1,mid+1,r,x,y);
tr[t]=tr[t<<1]+tr[t<<1|1];
}
int main(){
n=rd(),m=rd();
build(1,1,n);
for (;m--;){
op=rd(),x=rd(),y=rd();
if (op==1) wln(query(1,1,n,min(x,y),max(x,y)).all);
else update(1,1,n,x,y);
}
}