codevs 3981 动态最大子段和(线段树)
题目传送门:codevs 3981 动态最大子段和
题目还是简单一点好...
有n个数,a[1]到a[n]。
接下来q次查询,每次动态指定两个数l,r,求a[l]到a[r]的最大子段和。
子段的意思是连续非空区间。
第一行一个数n。
第二行n个数a[1]~a[n]。
第三行一个数q。
以下q行每行两个数l和r。
q行,每行一个数,表示a[l]到a[r]的最大子段和。
7
2 3 -233 233 -23 -2 233
4
1 7
5 6
2 5
2 3
441
-2
233
3
对于50%的数据,q*n<=10000000。
对于100%的数据,1<=n<=200000,1<=q<=200000。
a[1]~a[n]在int范围内,但是答案可能超出int范围。
数据保证1<=l<=r<=n。
空间128M,时间1s。
题目大意:
求解区间 a[l]~a[r] 的最大子段和
解题思路:
用线段树维护区间最大值。开几个变量存区间和sum,完全在左区间的最大值max_l,完全在右区间的最大值max_r,跨左右区间的最大值max。
#include <bits/stdc++.h>
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
using namespace std;
const int N = + ;
typedef long long int ll;
struct node
{
int l,r;
ll max_,max_l,max_r,sum;
} a[N<<];
int n,q,x,y;
ll ans;
void up(int rt)
{
a[rt].max_=max(max(a[rt<<].max_,a[rt<<|].max_),a[rt<<].max_r+a[rt<<|].max_l);
a[rt].max_l=max(a[rt<<].max_l,a[rt<<].sum+a[rt<<|].max_l);
a[rt].max_r=max(a[rt<<|].max_r,a[rt<<|].sum+a[rt<<].max_r);
a[rt].sum=a[rt<<].sum+a[rt<<|].sum;
}
void build(int rt,int l,int r)
{
a[rt].l=l,a[rt].r=r;
if (l==r)
{
scanf("%lld",&a[rt].max_);
a[rt].max_l=a[rt].max_r=a[rt].sum=a[rt].max_;
return ;
}
int mid = (l+r)>>;
build(lson);
build(rson);
up(rt);
}
void query(int rt,int L,int R,ll &ans,ll &ansl,ll &ansr)
{
if (L<=a[rt].l&&a[rt].r<=R)
{
ans=a[rt].max_;
ansl=a[rt].max_l;
ansr=a[rt].max_r;
return ;
}
int mid=(a[rt].l+a[rt].r)>>;
if (mid>=R) query(rt<<,L,R,ans,ansl,ansr);
else if (mid<L) query(rt<<|,L,R,ans,ansl,ansr);
else
{
ll lans=,lansl=,lansr=,rans=,ransl=,ransr=;
query(rt<<,L,R,lans,lansl,lansr);
query(rt<<|,L,R,rans,ransl,ransr);
ans=max(max(lans,rans),lansr+ransl);
ansl=max(lansl,ransl+a[rt<<].sum);
ansr=max(ransr,lansr+a[rt<<|].sum);
}
}
int main()
{
scanf("%d",&n);
build(,,n);
for ( scanf("%d",&q); q; q--)
{
scanf("%d%d",&x,&y);
ll ans=,ansl=,ansr=;
query(,x,y,ans,ansl,ansr);
printf("%lld\n",ans);
}
return ;
}
codevs 3981 动态最大子段和(线段树)的更多相关文章
- codevs 3981 动态最大子段和
3981 动态最大子段和 http://codevs.cn/problem/3981/ 题目等级 : 钻石 Diamond 题目描述 Description 题目还是简单一点好... 有n个 ...
- 【BZOJ3295】动态逆序对(线段树,树状数组)
[BZOJ3295]动态逆序对(线段树,树状数组) 题面 Description 对于序列A,它的逆序对数定义为满足iAj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的 ...
- 指针-动态开点&合并线段树
一个知识点不在一道题里说是没有灵魂的 线段树是用来处理区间信息的咯 但是往往因为需要4倍空间让许多人退却,而动态开点的线段树就非常棒 仿佛只用2倍就可以咯 指针保存位置,即节点信息,是很舒适的,所以用 ...
- BZOJ 4636 (动态开节点)线段树
思路: 偷懒 懒得离散化 搞了个动态开节点的线段树 (其实是一样的--..) 注意会有a=b的情况 要判掉 //By SiriusRen #include <cstdio> #includ ...
- zoj 2112 Dynamic Rankings 动态第k大 线段树套Treap
Dynamic Rankings Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.zju.edu.cn/onlinejudge/show ...
- LA 3938 动态最大连续和 线段树
题目链接: https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show ...
- Luogu P4643 【模板】动态dp(矩阵乘法,线段树,树链剖分)
题面 给定一棵 \(n\) 个点的树,点带点权. 有 \(m\) 次操作,每次操作给定 \(x,y\) ,表示修改点 \(x\) 的权值为 \(y\) . 你需要在每次操作之后求出这棵树的最大权独立集 ...
- [BZOJ3638 && BZOJ3272]带修区间不相交最大K子段和(线段树模拟费用流)
https://www.cnblogs.com/DaD3zZ-Beyonder/p/5634149.html k可重区间集问题有两种建图方式,可能这一种才可以被线段树优化. 换个角度看,这也是一个类似 ...
- luoguU60884 【模板】动态点分治套线段树
题目连接:https://www.luogu.org/problemnew/show/U60884 题意:有N个点,标号为1∼N,用N−1条双向带权通道连接,保证任意两个点能互相到达. Q次询问,问从 ...
随机推荐
- 命名实体识别视频51cto
https://edu.51cto.com/center/course/lesson/index?id=402918 https://edu.51cto.com/course/18466.html
- 深入java面向对象五:Java的内存管理
一. Java对象的引用种类 Java内存管理包括内存分配和内存回收, 这个动作都是由JVM自动完成,所以过多的内存分配增加了内存的消耗,且垃圾回收线程的不断运行会给后台增加压力,降低系统的性能. 1 ...
- java 集合类 & 容器
为什么出现集合类? 面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就要对对象进行存储,集合就是存储对象最常用的一种方式. 数组和集合类同是容器,有何不同? 数组虽然也可以存储 ...
- H3C 传递信息
- svn 删除、移动和改名
删除.移动和改名 Subversion allows renaming and moving of files and folders. So there are menu entries for d ...
- linux scull 的内存使用
在介绍读写操作前, 我们最好看看如何以及为什么 scull 进行内存分配. "如何"是需要全 面理解代码, "为什么"演示了驱动编写者需要做的选择, 尽管 sc ...
- 【9001】Internet消息发布
Time Limit: 1 second Memory Limit: 256 MB 问题描述 设Internet上有N个站点,通常从一个站点发送消息给其他N-1个站点,需依次发送N-1次.这样从一个站 ...
- java Eclipse的使用技巧
eclipse与myeclipse的关系(都属于java开发的工具): 后者是前者的一个插件,后来为了方便使用,myeclipse集合了eclipse,后者是收费的. 可大部分人都是用 eclipse ...
- H3C Hosts文件
- JavaScript中的forEach
语法:array.forEach(callbackfn[, thisArg]) 参数说明: array1 必需. 一个数组对象. callbackfn 必需. 一个接受最多三个参数的函数. 对 ...