[luogu SP1716 GSS3] Can you answer these queries III {线段树}

版权声明:请大家斧正,如喜欢的话,为拙见点一个赞吧。 https://blog.csdn.net/qq_39897867/article/details/81949585

题目

https://www.luogu.org/problemnew/show/SP1716


解题思路

在线段树上的每个节点上,除了区间端点外,在维护4个信息:区间和 s u m ,区间最大连续字段和 d a t ,紧靠左端的最大连续字段和 l m a x ,紧靠右端的最大连续字段和 r m a x
在线段树的正常模板下处理一下即可(不过我因为交换打错了, W A 了很久!!!)->

a [ k ] . s u m = a [ k 2 ] . s u m + a [ k 2 + 1 ] . s u m ;
a [ k ] . l m a x = m a x ( a [ k 2 ] . l m a x , a [ k 2 ] . s u m + a [ k 2 + 1 ] . l m a x ) ;
a [ k ] . r m a x = m a x ( a [ k 2 + 1 ] . r m a x , a [ k 2 + 1 ] . s u m + a [ k 2 ] . r m a x ) ;
a [ k ] . d a t = m a x ( m a x ( a [ k 2 ] . d a t , a [ k 2 + 1 ] . d a t ) , a [ k 2 ] . r m a x + a [ k 2 + 1 ] . l m a x ) ;


代码

#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); 
    }
}

猜你喜欢

转载自blog.csdn.net/qq_39897867/article/details/81949585