线段树裸题.
描述
给定长度为N的数列A,以及M条指令 (N≤500000, M≤100000),每条指令可能是以下两种之一:
“2 x y”,把 A[x] 改成 y。
“1 x y”,查询区间 [x,y] 中的最大连续子段和,即 max(x≤l≤r≤y) { ∑(i=l~r) A[i] }。
对于每个询问,输出一个整数表示答案。
输入格式
第一行两个整数N,M
第二行N个整数Ai
接下来M行每行3个整数k,x,y,k=1表示查询(此时如果x>y,请交换x,y),k=2表示修改
输出格式
对于每个询问输出一个整数表示答案。
样例输入
5 3
1 2 -3 4 5
1 2 3
2 2 -1
1 3 2
样例输出
2
-1
数据范围与约定
对于100%的数据: N≤500000, M≤100000, |Ai|<=1000
线段树只需维护4个参数,,分别表示区间从左起最大和,区间从右起最大和,区间最大连续子段和,区间和.
维护函数:
inline void upd(int x) {
s[x]=s[lc]+s[rc];
ls[x]=max(ls[lc],s[lc]+ls[rc]);
rs[x]=max(rs[rc],s[rc]+rs[lc]);
res[x]=max(max(res[lc],res[rc]),rs[lc]+ls[rc]);
}
查询的时候用两个变量:即可.
表示右端点为当前线段树区间左端点-1的最大连续子段和.
代码:
#include<cstdio>
#include<cctype>
#include<cstring>
#define g getchar()
#define lc (x<<1)
#define rc (x<<1|1)
#define max(x,y) (x>y?x:y)
using namespace std;
typedef long long ll;
const int N=1<<19;
const ll inf=1LL<<63;
template<class o>
inline void qr(o&x) {
char c=g;x=0;int f=1;
while(!isdigit(c)){if(c=='-')f=-1;c=g;}
while(isdigit(c))x=x*10+c-'0',c=g;
x*=f;
}
void write(ll x) {
if(x/10)write(x/10);
putchar(x%10+'0');
}
void pri(ll x) {
if(x<0)putchar('-'),x=-x;
write(x);puts("");
}
template<typename o>
inline void swap(o&x,o&y) { o t=x;x=y;y=t;}
ll res[N<<1],ls[N<<1],rs[N<<1],s[N<<1];
inline void upd(int x) {
s[x]=s[lc]+s[rc];
ls[x]=max(ls[lc],s[lc]+ls[rc]);
rs[x]=max(rs[rc],s[rc]+rs[lc]);
res[x]=max(max(res[lc],res[rc]),rs[lc]+ls[rc]);
}
void bt(int x,int l,int r) {
if(l==r){qr(s[x]);ls[x]=rs[x]=res[x]=s[x];return ;}
int mid=(l+r)>>1;
bt(lc,l,mid);
bt(rc,mid+1,r);
upd(x);
}
void change(int x,int l,int r,const int &pos,const ll &d) {
if(l==r){ls[x]=rs[x]=res[x]=s[x]=d;return ;}
int mid=(l+r)>>1;
if(pos<=mid)change(lc,l,mid,pos,d);
else change(rc,mid+1,r,pos,d);
upd(x);
}
ll ans,tmp;
void query(int x,int l,int r,const int &L,const int &R) {
if(L<=l&&r<=R) {
ans=max(ans,max(res[x],tmp+ls[x]));
tmp=max(tmp+s[x],max(rs[x],0LL));
return ;
}
int mid=(l+r)>>1;
if(L<=mid)query(lc,l,mid,L,R);
if(mid< R)query(rc,mid+1,r,L,R);
}
int main() {
register int n,m;qr(n);qr(m);bt(1,1,n);
int op;ll l,r;
while(m--) {
qr(op),qr(l);qr(r);
switch(op) {
case 1:
if(l>r)swap(l,r);
ans=inf;tmp=0;
query(1,1,n,l,r);
pri(ans);break;
case 2:
change(1,1,n,l,r);
break;
}
}
return 0;
}