zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    ASP.NET MVC 重点教程一周年版 第二回 UrlRouting
    ASP.NET MVC 重点教程一周年版 第三回 Controller与View
    DynamicData for Asp.net Mvc留言本实例 下篇 更新
    Asp.net MVC视频教程 18 单选与复选框
    使用ASP.NET MVC Futures 中的异步Action
    ASP.NET MVC RC 升级要注意的几点
    ATL、MFC、WTL CString 的今生前世
    msvcprt.lib(MSVCP90.dll) : error LNK2005:已经在libcpmtd.lib(xmutex.obj) 中定义
    关于Windows内存的一些参考文章
    Windows访问令牌相关使用方法
  • 原文地址:https://www.cnblogs.com/sto324/p/11297438.html
Copyright © 2011-2022 走看看