你能回答这些问题吗
题意:
给定长度为N的数列A,以及M条指令,每条指令可能是以下两种之一:
1、“1 x y”,查询区间 [x,y] 中的最大连续子段和,即 MAXx≤l≤r≤y{∑r,i=l A[i]}。
2、“2 x y”,把 A[x] 改成 y。
对于每个查询指令,输出一个整数表示答案。
思路:
用线段树维护一个区间和sum以及区间最大连续子段和dat,前缀最大连续子段和lmax,后缀最大连续子段和rmax。
容易推出pushup为
t[p].sum=t[p<<1].sum+t[p*2+1].sum;
t[p].lmax=max(t[p<<1].lmax,t[p<<1].sum+t[p*2+1].lmax);
t[p].rmax=max(t[p*2+1].rmax,t[p*2+1].sum+t[p<<1].rmax);
t[p].dat=max(max(t[p<<1].dat,t[p*2+1].dat),t[p<<1].rmax+t[p*2+1].lmax);
最后上代码
#include<cstdio> #include<cstring> #include<queue> #include<cmath> #include<algorithm> #include<map> #include<vector> #include<string> #include<set> #define ll long long using namespace std; const int N=500000<<2; int a[N>>2]; struct tree { int sum,l,r,lmax,rmax,dat; }t[N]; void pushup(int p) { t[p].sum=t[p<<1].sum+t[p*2+1].sum; t[p].lmax=max(t[p<<1].lmax,t[p<<1].sum+t[p*2+1].lmax); t[p].rmax=max(t[p*2+1].rmax,t[p*2+1].sum+t[p<<1].rmax); t[p].dat=max(max(t[p<<1].dat,t[p*2+1].dat),t[p<<1].rmax+t[p*2+1].lmax); } void build(int p,int l,int r) { t[p].l=l; t[p].r=r; if(l==r) { t[p].sum=t[p].lmax=t[p].rmax=t[p].dat=a[l]; return; } int mid=(l+r)>>1; build(p<<1,l,mid); build(p*2+1,mid+1,r); pushup(p); } void change(int p,int x,int v) { if (t[p].l==t[p].r) { t[p].dat=v; t[p].sum=v; t[p].lmax=v; t[p].rmax=v; return; } int mid=(t[p].l+t[p].r)>>1; if (x<=mid) change(p<<1,x,v); else change(p*2+1,x,v); pushup(p); } tree ask(int p,int l,int r) { if (l<=t[p].l && r>=t[p].r) return t[p]; int mid=(t[p].l+t[p].r)>>1,val=-(1<<30); tree a,b,c; a.dat=a.sum=a.lmax=a.rmax=val; b.dat=b.sum=b.lmax=b.rmax=val; c.sum=0; if(l<=mid) { a=ask(p<<1,l,r); c.sum+=a.sum; } if(r>mid) { b=ask(p*2+1,l,r); c.sum+=b.sum; } c.dat=max(max(a.dat,b.dat),a.rmax+b.lmax); c.lmax=max(a.lmax,b.lmax+a.sum); if(l>mid) c.lmax=max(c.lmax,b.lmax); c.rmax=max(b.rmax,b.sum+a.rmax); if(r<=mid) c.rmax=max(c.rmax,a.rmax); return c; } int main() { int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&a[i]); build(1,1,n); while(m--) { int k,x,y; scanf("%d%d%d",&k,&x,&y); if(k==1) { if(x>y) swap(x,y); tree r=ask(1,x,y); printf("%d\n",r.dat); } if(k==2) { change(1,x,y); } } }