zoukankan      html  css  js  c++  java
  • 线段树之成段更新(区间最大连续和)

    题目描述:

    给定一个含有N个整数的序列,它们的下标从1到N,对该序列进行如下2种操作;
    0 a b将下标为a的值变为b。
    1 a b求下标[a,b]之间的最大连续和

    解题思路:

    每一段区间当中必须记录相应的值以便于更新,其中的值包括了该区间的最大左连续和、最大右连续和、最大连续和以及总和,如图分析:

    那么线段树此时从下往上更新的时候,合并区间时,那么对于此时我们要维护的区间最大连续和最多有三个值能够取,左区间最大连续和、右区间最大连续和、左区间的右最大连续和 + 右区间的左最大连续和,那么此时维护起来就特别的简单了。。

    代码如下:

    View Code
     1 #include<iostream>
     2 #include<stdio.h>
     3 using namespace std;
     4 const int N = 50003;
     5 struct node
     6 {
     7        int mmax,lmax,rmax,sum;       
     8 }tree[N<<2];
     9 void pushup(int t)
    10 {
    11      int t1=t<<1;
    12      int t2=t1|1; 
    13      tree[t].sum=tree[t1].sum+tree[t2].sum;
    14      tree[t].mmax=max(tree[t1].mmax,tree[t2].mmax);
    15      tree[t].mmax=max(tree[t].mmax,tree[t1].rmax+tree[t2].lmax);
    16      tree[t].lmax=max(tree[t1].lmax,tree[t1].sum+tree[t2].lmax);
    17      tree[t].rmax=max(tree[t2].rmax,tree[t2].sum+tree[t1].rmax);
    18 }
    19 void build(int t,int l,int r)
    20 {
    21      if(l==r)
    22      {
    23         scanf("%d",&tree[t].sum);
    24         tree[t].mmax=tree[t].lmax=tree[t].rmax=tree[t].sum;
    25         return ;
    26      }
    27      int m=(l+r)>>1;
    28      build(t<<1,l,m);
    29      build(t<<1|1,m+1,r);
    30      pushup(t);
    31 }
    32 void update(int t,int l,int r,int i,int val)
    33 {
    34      if(l==r)
    35      {
    36          tree[t].lmax=tree[t].rmax=tree[t].mmax=tree[t].sum=val;
    37          return ;
    38      }
    39      int m=(l+r)>>1;
    40      if(i<=m)update(t<<1,l,m,i,val);
    41      else update(t<<1|1,m+1,r,i,val);
    42      pushup(t);
    43 }
    44 node query(int t,int l,int r,int L,int R)
    45 {
    46      if(L<=l&&r<=R)
    47      return tree[t];
    48      int m=(l+r)>>1;
    49      node ans1,ans2,ans;
    50      int flag1=0,flag2=0;
    51      if(L<=m){ans1=query(t<<1,l,m,L,R);flag1=1;}
    52      if(R>m){ans2=query(t<<1|1,m+1,r,L,R);flag2=1;}
    53      if(flag1&&flag2)
    54      {
    55         ans.sum=ans1.sum+ans2.sum;
    56         ans.lmax=max(ans1.lmax,ans1.sum+ans2.lmax);
    57         ans.rmax=max(ans2.rmax,ans2.sum+ans1.rmax);
    58         ans.mmax=max(max(ans1.mmax,ans2.mmax),ans1.rmax+ans2.lmax);
    59      }
    60      else
    61      {
    62         if(flag1) ans=ans1;
    63         else   ans=ans2;
    64      }
    65      return ans;
    66 }
    67 int main()
    68 {
    69     int n,m,order,a,b;
    70     while(~scanf("%d%d",&n,&m))
    71     {
    72           build(1,1,n);
    73           for(int i=0;i<m;i++)
    74           {
    75               scanf("%d%d%d",&order,&a,&b);
    76               if(order)
    77               {
    78                  if (a>b)swap(a,b); 
    79                  node ans=query(1,1,n,a,b);
    80                  printf("%d\n",ans.mmax);
    81               }
    82               else
    83               update(1,1,n,a,b);        
    84           }
    85     }
    86     return 0;    
    87 }
  • 相关阅读:
    java (java.exe) 解释器 -D 选项
    Ubuntu 12.04.3 X64 使用 NFS 作为文件共享存储方式 安装 Oracle11g RAC
    Ubuntu下 Oracle sqldeveloper中文目录、文件,select查询结果中:中文乱码
    行测题型
    Left join on where 区别
    常见公文——决定和请示
    宜家沙发测评
    "放管服"改革 清单
    shell && and ||
    ORA-01722: invalid number
  • 原文地址:https://www.cnblogs.com/nuoyan2010/p/2735102.html
Copyright © 2011-2022 走看看