• SP1716 GSS3


    题意

    给出n个数,q次操作,两种操作:把ax改成y,求[l,r]的最大子段和。

    n,m<=50000,-10000<=ai<=10000

    题解

    区间问题想到用线段树维护,考虑如何合并区间。

    当我们求出两段小区间的最大子段和,那么大区间的最大子段和可能是这两个的其中一个,也可能是中间两个区间拼接的部分,这部分就是左区间右边最大的部分和右区间左边最大的部分组成。

    所以我们还需要记录区间紧靠左边和紧靠右边的最大子段和,现在考虑维护左边的最大子段和lmax,在区间合并时,大区间的lmax可能是左区间的lmax,也可能是左边整个区间加上右边区间的lmax。rmax同理。

    区间查询的时候传结构体才能合并信息。

    #include<cstdio>
    #include<cstring>
    using namespace std;
    
    #define ls rt<<1
    #define rs rt<<1|1
    #define ll long long
    const int maxn=50005;
    int n,m;
    int a[maxn];
    struct cx{
      ll sum,dat,lmax,rmax;// 区间和,区间最大子段和,左端最大子段和,右端最大子段和
    }t[maxn<<2];
    
    ll max(ll x,ll y){return x>y ? x : y ;}
    
    void get(cx &ret,cx lx,cx ry){
      ret.sum=lx.sum+ry.sum;
      ret.lmax=max(lx.lmax,lx.sum+ry.lmax);
      ret.rmax=max(ry.rmax,ry.sum+lx.rmax);
      ret.dat=max(max(lx.dat,ry.dat),lx.rmax+ry.lmax);
    }
    
    void build(int rt,int l,int r){
      if(l==r){
        t[rt]=(cx){a[l],a[l],a[l],a[l]};
        return ;
      }
      int mid=(l+r)>>1;
      build(ls,l,mid);
      build(rs,mid+1,r);
      get(t[rt],t[ls],t[rs]);
    }
    
    cx query(int rt,int l,int r,int a_l,int a_r){
      //printf("%d %d %d %d 
    ",l,r,a_l,a_r);
      if(a_l<=l&&r<=a_r) return t[rt];
      int mid=(l+r)>>1;
      if(a_r<=mid) return query(ls,l,mid,a_l,a_r);
      if(mid<a_l) return query(rs,mid+1,r,a_l,a_r);
      cx ret,x,y;
      x=query(ls,l,mid,a_l,a_r);
      y=query(rs,mid+1,r,a_l,a_r);
      get(ret,x,y);
      return ret;
    }
    
    void modify(int rt,int l,int r,int pos,int val){
      if(l==r){
        t[rt]=(cx){val,val,val,val};
        return ;
      }
      int mid=(l+r)>>1;
      if(pos<=mid) modify(ls,l,mid,pos,val);
      else modify(rs,mid+1,r,pos,val);
      get(t[rt],t[ls],t[rs]);
    }
    
    int main(){
      scanf("%d",&n);
      for(int i=1;i<=n;i++) scanf("%d",&a[i]);
      build(1,1,n);
      scanf("%d",&m);
      for(int i=1;i<=m;i++){
        int opt;
        scanf("%d",&opt);
        if(opt){
          int l,r;
          scanf("%d%d",&l,&r);
          printf("%lld
    ",query(1,1,n,l,r).dat);
        }
        else {
          int pos,val;
          scanf("%d%d",&pos,&val);
          modify(1,1,n,pos,val);
        }
      }
    }
    View Code
  • 相关阅读:
    1接口编程
    EXCEL读写NPOI--导出功能
    EXCEL读写NPOI
    多条件查询
    基础数据管理
    C#经典入门第22章XML-1
    数据访问C#入门经典第21章-监控文件系统
    数据访问C#入门经典第21章-读写压缩数据
    Tensorflow笔记(基础):池化函数
    4.2 Tensorflow笔记:池化函数
  • 原文地址:https://www.cnblogs.com/sto324/p/11297438.html
Copyright © 2020-2023  润新知