题目链接:点击查看

题目大意:给出一个长度为n的序列,进行m次操作:

  1. 1 x y  查询区间[l,r]中的最大连续子段和
  2. 0 x y  将第x个数修改为y

题目分析:因为涉及到单点修改和区间查询等操作,所以可以选择线段树和树状数组,但又因为需要维护的变量比较多,所以我们选择用线段树操作方便点。因为要维护每个区间段的最大连续子段和,所以我们需要像区间合并那种题目一样,另外维护四个变量,ll,rr,all,sum分别表示区间内从左端开始的最大连续子段和,从右端开始的最大连续子段和,该区间内的最大连续子段和,该区间的权值和。


转移状态时,我们需要考虑全所有的情况再写pushup函数:

  1. sum:这个最简单,等于左右儿子区间和之和
  2. 关于ll变量:要从下面几点中取最大值:
    1. 左儿子的ll
    2. 左儿子的sum+右儿子的ll
  3. 关于rr变量:同样要从下面几点中取最大值:
    1. 右儿子的rr
    2. 右儿子的sum+左儿子的rr
  4. 关于all变量:从下面几点中取最大值:
    1. 左儿子的all
    2. 右儿子的all
    3. 左儿子的rr+右儿子的ll

这样一梳理,就解决了一大半的难点了,只要照着一句一句实现就好了,下面在讲一下这个题目比较难想的query,即查询函数

因为涉及到区间合并,我们同样也要分三个阶段来分类讨论:

  1. 所求区间全部都在当前区间的左儿子区间内:继续进入左儿子递归
  2. 所求区间全部都在当前区间的右儿子区间内:继续进入右儿子递归
  3. 所求区间既在左儿子的区间,又在右儿子的区间内:将左右儿子递归后的结果储存到结构体中,对这两个结构体进行类似于pushup的操作来达到区间合并的效果,最后返回结构体

直接上代码了:

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<cmath>
#include<sstream>
using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=5e4+100;struct Node
{int ll,rr,sum,all;int l,r;
}tree[N<<2];void pushup(int k)
{tree[k].ll=max(tree[k<<1].ll,tree[k<<1].sum+tree[k<<1|1].ll);tree[k].rr=max(tree[k<<1|1].rr,tree[k<<1|1].sum+tree[k<<1].rr);tree[k].all=max(max(tree[k<<1].all,tree[k<<1|1].all),tree[k<<1].rr+tree[k<<1|1].ll);tree[k].sum=tree[k<<1].sum+tree[k<<1|1].sum;
}void build(int k,int l,int r)
{tree[k].l=l;tree[k].r=r;if(l==r){scanf("%d",&tree[k].sum);tree[k].ll=tree[k].rr=tree[k].all=tree[k].sum;return;}int mid=(l+r)>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);pushup(k);
}void update(int k,int pos,int val)
{if(tree[k].l==tree[k].r){tree[k].sum=tree[k].ll=tree[k].rr=tree[k].all=val;return;}int mid=(tree[k].r+tree[k].l)>>1;if(mid>=pos)update(k<<1,pos,val);elseupdate(k<<1|1,pos,val);pushup(k);
}Node query(int k,int l,int r)//注意查询函数返回的是结构体,方便对左右儿子区间进行合并的操作
{if(tree[k].l>=l&&tree[k].r<=r)return tree[k];int mid=(tree[k].l+tree[k].r)>>1;if(mid>=r)return query(k<<1,l,r);else if(mid<l)return query(k<<1|1,l,r);else{Node a,b,ans;a=query(k<<1,l,r);b=query(k<<1|1,l,r);ans.sum=a.sum+b.sum;ans.ll=max(a.ll,a.sum+b.ll);ans.rr=max(b.rr,b.sum+a.rr);ans.all=max(max(a.all,b.all),a.rr+b.ll);return ans;}
}int main()
{
//  freopen("input.txt","r",stdin)int n,m;while(scanf("%d",&n)!=EOF){build(1,1,n);scanf("%d",&m);while(m--){int op,x,y;scanf("%d%d%d",&op,&x,&y);if(op==1){Node temp=query(1,x,y);cout<<temp.all<<endl;}else{update(1,x,y);}
//          cout<<endl;
//          for(int i=1;i<=10;i++)
//              cout<<tree[i].l<<' '<<tree[i].r<<' '<<tree[i].ll<<' '<<tree[i].rr<<' '<<tree[i].all<<' '<<tree[i].sum<<endl;}}return 0;
}

SPOJ - GSS3 Can you answer these queries III(线段树+区间合并)相关推荐

  1. SPOJ GSS2 Can you answer these queries II (线段树离线) - xgtao -

    Can you answer these queries II 这是一道线段树的题目,维护历史版本,给出N(<=100000)个数字(-100000<=x<=100000),要求求出 ...

  2. HDU 4027 Can you answer these queries?(线段树/区间不等更新)

    传送门 Can you answer these queries? Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65768/6576 ...

  3. spoj 2916. Can you answer these queries V(线段树)

    题目链接:http://www.spoj.com/problems/GSS5/ 题意:给出n个数,求区间最大子段和,但是限制了子段的起点终点,起点要在[x1,y1]内,终点要在[x2,y2]内. 思路 ...

  4. Can you answer these queries III (线段树维护最大子段和)

    题意: 求一个区间的最大连续和. 0:表示把A[x]改成y 1:表示求[x,y]这个区间的最大连续和. 题解: 线段树维护四个变量. 倒着讲,先来看如何维护这四个变量. summax代表这个区间连续最 ...

  5. CF911G Mass Change Queries (线段树区间 合并)

    题意: 给出一个数列,有q个操作,每种操作是把区间[l,r]中等于x的数改成y.输出q步操作完的数列. 题解: 100个数,很容易想到要从这里进行突破,对于某次操作我们只需要把这个区间的数x给移动到y ...

  6. SPOJ GSS3-Can you answer these queries III-分治+线段树区间合并

    Can you answer these queries III SPOJ - GSS3 这道题和洛谷的小白逛公园一样的题目. 传送门: 洛谷 P4513 小白逛公园-区间最大子段和-分治+线段树区间 ...

  7. [HDOJ4027]Can you answer these queries?(线段树,特殊成段更新,成段查询)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4027 RT,该题要求每次更新是更新所有节点,分别求平方根,查询是求和.昨晚思前想后找有没有一个数学上的 ...

  8. 线性代数四之动态DP(广义矩阵加速)——Can you answer these queries III,保卫王国

    动态DP--广义矩阵加速 SP1716 GSS3 - Can you answer these queries III description solution code [NOIP2018 提高组] ...

  9. 【Codeforces717F】Heroes of Making Magic III 线段树 + 找规律

    F. Heroes of Making Magic III time limit per test:3 seconds memory limit per test:256 megabytes inpu ...

最新文章

  1. PostgreSQL索引走错一例分析
  2. 关系数据库标准语言 SQL (ch.3)
  3. RNA干扰各种方法优缺点简介?
  4. 【初窥javascript奥秘之闭包】叶大侠病都好了,求不踩了:)
  5. 59-混沌操作法感悟2.(2015.2.25)
  6. Domino的压缩数据库的Load Compact命令
  7. linux进程timer,Linux Timer 示例
  8. html5 canvas 获取当前坐标,html5 canvas fillRect坐标和大小的问题解决方法
  9. msp430和stm32 dht11驱动程序
  10. Kafka无法消费?!我的分布式消息服务Kafka却稳如泰山!
  11. NoSQL-Mongodb基本操作和复制集(一)
  12. 已知函数和y值求自变量用matlab,matlab已知函数值求自变量,求助
  13. linux内核书籍推荐
  14. java投票_java做投票系统
  15. 营销互动新玩法——积分商城
  16. 苹果电脑的超强文件压缩软件——FastZip
  17. Android 代码混淆 R8与Proguard
  18. 工业设备振动无线智能监测方案
  19. 参与社区活动获得奖励
  20. 正厚知识 | 人工智能会取代人类吗?(下)

热门文章

  1. MySQL服务的启动和停止
  2. Zookeeper的一致性是什么情况?
  3. MyBatis 实际使用案例-Mapper.xml 映射配置文件【重点】
  4. 从Servlet 到ApplicationContext
  5. 简单分析EnableAutoConfiguration
  6. 微信支付 - 构建商户订单
  7. 对称加密-DES解密
  8. 异常注意事项_finally有return语句
  9. webclientt和httpwebrequest
  10. 基于 HTML5 的 WebGL 3D 档案馆可视化管理系统