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; }; //.. ...
随机推荐
- faster-rcnn CUDA8.0编译错误
之前编译Faster-RCNN的时候用的都是CUDA7.5,最近换了机器,变成了CUDA8.0,果然编译出现错误了…… 参考下面这篇博客解决了问题: http://blog.csdn.net/kexi ...
- IdentityServer4入门四:应用Implicit模式保护网站(下)
为认证服务端增加数据库支持 我计划使用一个名为Admin的表,放在一个已有的数据库里.所以我需要定义Admin类和在配置里预先加上数据库连接 新增类:Admin.cs public class Adm ...
- エンジニア死滅シタ世界之学べない学校 [MISSION LEVEL: C]-Python3
答案 # coding: utf-8 # 自分の得意な言語で # Let's チャレンジ!! N=input() w_a=0 w_b=0 gpc_dict={ "gg":0,&qu ...
- Comet OJ - Contest #6 B.双倍快乐(二维最大上升子序列和)
双倍快乐 题目描述 Illyasviel:"你想要最长不下降子序列吗?" star-dust:"好啊!" Illyasviel:"老板,给我整两个最长 ...
- python 可执行
py2exe使用方法 py2exe作者:zzj 日期:2006-07-05字体大小: 小 中 大 一.简介 py2exe是一个将python脚本转换成windows上的可独立执行的可执行程序(*.ex ...
- 每天一个linux命令:top命令
top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器.下面详细介绍它的使用方法.top是一个动态显示过程,即可以通过用户按键来不断刷新 ...
- vmware 两删除一清空
快速处理办法: cat /etc/sysconfig/network-scripts/ifcfg-eth0 sed -i '/UUID/d' /etc/sysconfig/network-script ...
- osg osgUtil::LineSegmentIntersector
#ifdef _WIN32 #include <Windows.h> #endif // _WIN32 #include <osgViewer/Viewer> #include ...
- 算法习题---3.11换抵挡装置(UVa1588)
一:题目 给你连个长度分别为n1,n2且每列高度只为1或2的长条,然后将他们拼在一起,高度不能超过3,问他们拼在一起的最短长度 二:实现思路 1.获取主动轮和从动轮的数据. 2.主动轮不动,从动轮从左 ...
- (五)Centos之目录处理命令
一.目录处理命令 linux中 关于目录 有几个重要概念:一个是 / 根目录 还有一个当前用户的家目录 比如 root用户的家目录是 /root ,普通用户的家目录是/home/xxx 下,如下图 ...