poj 2750

线段树

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int n,q;
struct node{
    int l,r;
    int sum;
    int amax,amin;    //区间最大、小序列和
    int lmax,rmax;    //区间最左、右连续最大和
    int lmin,rmin;    //区间最左、右连续最小和
}tree[300000];
void build(int s,int t,int id){
    tree[id].l=s,tree[id].r=t;
    tree[id].sum=0;
    tree[id].amax=tree[id].lmax=tree[id].rmax=-1000000000;
    tree[id].amin=tree[id].lmin=tree[id].rmin= 1000000000;
    if(s!=t){
        int mid=(s+t)>>1;
        build(s,mid,id*2);
        build(mid+1,t,id*2+1);
    }
}
void updatelength(int id){
    tree[id].sum=tree[id*2].sum+tree[id*2+1].sum;
    tree[id].amax=max(max(tree[id*2].amax,tree[id*2+1].amax),tree[id*2].rmax+tree[id*2+1].lmax);
    tree[id].amin=min(min(tree[id*2].amin,tree[id*2+1].amin),tree[id*2].rmin+tree[id*2+1].lmin);
    tree[id].lmax=tree[id*2].lmax;
    tree[id].lmin=tree[id*2].lmin;
    tree[id].rmax=tree[id*2+1].rmax;
    tree[id].rmin=tree[id*2+1].rmin;

    if(tree[id*2].lmax<tree[id*2].sum+tree[id*2+1].lmax)         //注意在更新tree[id*2].lmax等这四个变量时有一些问题
        tree[id].lmax=tree[id*2].sum+tree[id*2+1].lmax;
    if(tree[id*2].lmin>tree[id*2].sum+tree[id*2+1].lmin)
        tree[id].lmin=tree[id*2].sum+tree[id*2+1].lmin;

    if(tree[id*2+1].rmax<tree[id*2+1].sum+tree[id*2].rmax)
        tree[id].rmax=tree[id*2+1].sum+tree[id*2].rmax;
    if(tree[id*2+1].rmin>tree[id*2+1].sum+tree[id*2].rmin)
        tree[id].rmin=tree[id*2+1].sum+tree[id*2].rmin;
}
void update(int s,int tem,int id){
    if(tree[id].l==tree[id].r){
        tree[id].sum=tem;
        tree[id].amax=tree[id].amin=tree[id].lmax=tree[id].lmin=tree[id].rmax=tree[id].rmin=tem;
        return ;
    }
    int mid=(tree[id].l+tree[id].r)>>1;
    if(mid>=s)
        update(s,tem,id*2);
    else
        update(s,tem,id*2+1);
    updatelength(id);
}
int main(){
    int i,j,pos,tem;
    scanf("%d",&n);
    build(1,n,1);
    for(i=1;i<=n;i++){
        scanf("%d",&tem);
        update(i,tem,1);
    }
    scanf("%d",&q);
    for(i=1;i<=q;i++){
        scanf("%d %d",&pos,&tem);
        update(pos,tem,1);
        if(tree[1].amax==tree[1].sum)
            printf("%d\n",tree[1].amax-tree[1].amin);
        else if(tree[1].amax>=tree[1].sum-tree[1].amin)          //考虑到环的性质,最左边的线段连接最右边的线段这种情况也可能产生最大值
            printf("%d\n",tree[1].amax);
        else if(tree[1].amax<tree[1].sum-tree[1].amin)          //但是此时最大值为环总和减去最小连续和,而不是tree[1].lmax+tree[1].rmax
            printf("%d\n",tree[1].sum-tree[1].amin);
    }
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值