Can you answer on these queries 3 SPOJ GSS3 线段树

题意:

给定长度为N的数列A,以及M条指令(N,M<=50000),每条指令可能是以下两种之一:

1."0 x y",把A【x】改成y。

2."1 x y",查询区间[x,y]中的最大连续子段和。

对于每次询问,输出一个整数表示答案。

 

分析:
一个区间的最大连续子段和只有三种情况。

图片来自:https://www.cnblogs.com/shenben/p/6361623.html

#include <bits/stdc++.h>

using namespace std;
#define N 100005
#define lson rt<<1
#define rson rt<<1|1

int a[N];
struct TREE{
    int sum,gss,lgss,rgss;
}tr[N<<2];
void updata(int rt){
    tr[rt].sum = tr[lson].sum+tr[rson].sum;
    tr[rt].lgss = max(tr[lson].lgss,tr[lson].sum+tr[rson].lgss);
    tr[rt].rgss = max(tr[rson].rgss,tr[rson].sum+tr[lson].rgss);
    tr[rt].gss = max(max(tr[lson].gss,tr[rson].gss),tr[lson].rgss+tr[rson].lgss);
}
void bulid(int rt,int l,int r){
    if(l == r){
        tr[rt].sum = tr[rt].gss = tr[rt].lgss = tr[rt].rgss = a[l];
        return;
    }
    int mid = l+r>>1;
    bulid(lson,l,mid);
    bulid(rson,mid+1,r);
    updata(rt);
}
TREE query(int rt,int l,int r,int x,int y){
    if(l == x&&r == y)return tr[rt];
    int mid = l+r>>1;
    if(y<=mid)return query(lson,l,mid,x,y);
    else if(x>mid)return query(rson,mid+1,r,x,y);
    else {
        TREE left,right,result;
        left = query(lson,l,mid,x,mid);
        right = query(rson,mid+1,r,mid+1,y);
        result.sum = left.sum = right.sum;
        result.lgss = max(left.lgss,left.sum+right.lgss);
        result.rgss = max(right.rgss,right.sum+left.rgss);
        result.gss = max(left.gss,max(right.gss,left.rgss+right.lgss));
        return result;
    }
}
int main(){
    int n,Que,x,y;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    bulid(1,1,n);
    scanf("%d",&Que);
    for(int i=0;i<Que;i++){
        scanf("%d%d",&x,&y);
        printf("%d\n",query(1,1,n,x,y).gss);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值