Can you answer these queries III
Can you answer these queries III
题目:洛谷 SPOJ
【题目描述】
给定长度为N的数列A,以及M条指令,每条指令可能是以下两种之一:
1.“0 x y”,把A[x]改成y;
2.“1 x y”,查询区间[x,y]中的最大连续子段和。
【输入格式】
第一行,N;
第二行,N个数,即A[1]...A[N];
第三行,M;
第4至第M+3行,每行三个整数,分别表示“0或1”,x,y,即指令。
【输出格式】
i行,i表示“1 x y”的数量,每行1个整数,即指令2的答案。
【数据规模】
N,M<=50000。
解析
查询区间最大连续子段和,显然可以用线段树维护序列。
先分析一下,在线段树中,对于查询的每个区间[x,y],会有以下两种情况:
1、如图所示,区间刚好在一个子树中,只需查询该子树的区间最大连续子段和即可;
2、如图所示,区间一部分在左子树中,另一部分在右子树中,对于这种情况,该区间的最大连续子段和为左子树的最大后缀和加上右子树的最大前缀和。
考虑完所有情况后,只需套上线段树模板再稍作修改即可。
Code
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
#include <queue>
using namespace std;
struct rec{
int l,r,maxn,lmax,rmax,sum;//lmax最大前缀和,rmax最大后缀和
}t[];
int n,m,a[];
void build(int p,int l,int r)
{
t[p].l=l,t[p].r=r;
if(l==r)
{
t[p].sum=t[p].lmax=t[p].rmax=t[p].maxn=a[l];
return ;
}
int mid=(l+r)/;
build(p*,l,mid);
build(p*+,mid+,r);
t[p].sum=t[p*].sum+t[p*+].sum;
t[p].lmax=max(t[p*].lmax,t[p*].sum+t[p*+].lmax);
t[p].rmax=max(t[p*+].rmax,t[p*+].sum+t[p*].rmax);
t[p].maxn=max(t[p*].rmax+t[p*+].lmax,max(t[p*].maxn,t[p*+].maxn));
return ;
}
void change(int p,int x,int v)
{
if(t[p].l==t[p].r)
{
t[p].sum=t[p].rmax=t[p].lmax=t[p].maxn=v;
return ;
}
int mid=(t[p].l+t[p].r)/;
if(x<=mid) change(p*,x,v);
else change(p*+,x,v);
t[p].sum=t[p*].sum+t[p*+].sum;
t[p].lmax=max(t[p*].lmax,t[p*].sum+t[p*+].lmax);
t[p].rmax=max(t[p*+].rmax,t[p*+].sum+t[p*].rmax);
t[p].maxn=max(t[p*].rmax+t[p*+].lmax,max(t[p*].maxn,t[p*+].maxn));
}
rec ask(int p,int l,int r)
{
if(l<=t[p].l&&r>=t[p].r) return t[p];
rec a,b,ans;
a.sum=a.lmax=a.rmax=a.maxn=b.sum=b.lmax=b.rmax=b.maxn=0xcfcfcfcf;
ans.sum=;
int mid=(t[p].l+t[p].r)/;
if(l<=mid)
{
a=ask(p*,l,r);
ans.sum+=a.sum;
}
if(r>mid)
{
b=ask(p*+,l,r);
ans.sum+=b.sum;
}
ans.maxn=max(max(a.maxn,b.maxn),a.rmax+b.lmax); //注意负数
ans.lmax=max(a.lmax,a.sum+b.lmax);
ans.rmax=max(b.rmax,b.sum+a.rmax);
if(l>mid) ans.lmax=max(ans.lmax,b.lmax);
if(r<=mid) ans.rmax=max(ans.rmax,a.rmax);
//分类讨论
return ans;
}
int main()
{
int c,l,r;
cin>>n;
for(int i=;i<=n;i++) cin>>a[i];
build(,,n);
cin>>m;
for(int i=;i<=m;i++)
{
cin>>c>>l>>r;
if(c==) change(,l,r);
else cout<<ask(,l,r).maxn<<endl;
}
return ;
}
Can you answer these queries III的更多相关文章
- SPOJ GSS3 Can you answer these queries III[线段树]
SPOJ - GSS3 Can you answer these queries III Description You are given a sequence A of N (N <= 50 ...
- GSS3 SPOJ 1716. Can you answer these queries III gss1的变形
gss2调了一下午,至今还在wa... 我的做法是:对于询问按右区间排序,利用splay记录最右的位置.对于重复出现的,在splay中删掉之前出现的位置所在的节点,然后在splay中插入新的节点.对于 ...
- 数据结构(线段树):SPOJ GSS3 - Can you answer these queries III
GSS3 - Can you answer these queries III You are given a sequence A of N (N <= 50000) integers bet ...
- 线段树 SP1716 GSS3 - Can you answer these queries III
SP1716 GSS3 - Can you answer these queries III 题意翻译 n 个数,q 次操作 操作0 x y把A_xAx 修改为yy 操作1 l r询问区间[l, r] ...
- 「 SPOJ GSS3 」 Can you answer these queries III
# 题目大意 GSS3 - Can you answer these queries III 需要你维护一种数据结构,支持两种操作: 单点修改 求一个区间的最大子段和 # 解题思路 一个区间的最大子段 ...
- Can you answer these queries III(线段树)
Can you answer these queries III(luogu) Description 维护一个长度为n的序列A,进行q次询问或操作 0 x y:把Ax改为y 1 x y:询问区间[l ...
- SPOJ GSS3 Can you answer these queries III
Time Limit: 330MS Memory Limit: 1572864KB 64bit IO Format: %lld & %llu Description You are g ...
- spoj 1557 GSS3 - Can you answer these queries III 线段树
题目链接 给出n个数, 2种操作, 一种是将第x个数改为y, 第二种是询问区间[x,y]内的最大连续子区间. 开4个数组, 一个是区间和, 一个是区间最大值, 一个是后缀的最大值, 一个是前缀的最大值 ...
- SP1716 GSS3 - Can you answer these queries III
题面 题解 相信大家写过的传统做法像这样:(这段代码蒯自Karry5307的题解) struct SegmentTree{ ll l,r,prefix,suffix,sum,maxn; }; //.. ...
随机推荐
- C++中的平方、开方、绝对值怎么计算
#include <math.h> //平方 pow() ,);// 4的平方=16 //开方 ,0.5);// 4的平方根=2 );// 4的平方根=2 //整数绝对值 int c = ...
- ajax请求数据动态填充之文档与字符串区别手法
success: function(data){ if(data.status==200){ var realName=data.doc.realName; $("#yishiul" ...
- A·F·O小记
看过很多的游记,也看过很多的退役记.回忆录,而当自己真正去面对的那一刻,却又不知道从何说起,也不知道能用怎样的形式和语言,才能把这段珍贵的记忆封存起来,留作青春里的一颗璀璨明珠…… 还是随便写写吧…… ...
- Oracle plsql 触发器 查询/启用/停止
在PLSQL中查询某个表的触发器脚本 select * from user_triggers where table_name='xxx' oracle触发器的启用和停用 1.禁用 table_nam ...
- 使用python3安装frida-tools出错
执行安装命令 pip3.6 install frida-tools 得到错误信息 error: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] c ...
- LINUX增加SWAP分区---install_oracle
我们都知道在安装Linux系统时在分区时可以分配swap分区,而系统安装后(在运行中)如何建立或调整swap分区呢?在装完Linux系统之后,建立Swap分区有两种方法.1.新建磁盘分区作为swap分 ...
- 建站之星v2.7快速更换模版
网站建设很多人使用建站之星因为它的拖拽功能非常友好.但是很多人不会使用建站之星更换模版,网上的教程又复杂难懂,现在教大家一个简单快捷的办法. 方法/步骤 废话不多说,从模版目录找到你喜欢的模版 ...
- struct ifreq 获取IP 和mac和修改mac
2012-09-11 14:26 struct ifreq 获取IP 和mac和修改mac 配置ip地址和mask地址: ifconfig eth0 192.168.50.22 netmask 25 ...
- 001-java 设计模式概述
一.概述 思维导图 GoF(“四人帮”,又称Gang of Four,即Erich Gamma, Richard Helm, Ralph Johnson & John Vlissides) 1 ...
- 不同操作系统上DNS客户端操作区别汇总
结论:windows有DNS缓存,Linux默认无DNS缓存,只能依赖于安装其他软件. 一.不同操作系统的客户端的DNS缓存差别 1.windows 系统中dns 解析器会使用系统的dns缓存来提高d ...