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次询问,问从 ...
随机推荐
- poj 1787 Charlie's Change (多重背包可作完全背包)
Charlie's Change Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 3792 Accepted: 1144 ...
- Vue 路由的嵌套使用
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- H3C 通配符掩码的应用示例
- H3C 出站包过滤工作流程
- 【u232】围棋游戏
Time Limit: 1 second Memory Limit: 128 MB [问题描述] 为了增强幼儿园小朋友的数数能力,小虎老师给了一个家庭游戏作业.让小虎那一块空的围棋盘,随机在一些方格中 ...
- HDU 1828“Picture”(线段树+扫描线求矩形周长并)
传送门 •参考资料 [1]:算法总结:[线段树+扫描线]&矩形覆盖求面积/周长问题(HDU 1542/HDU 1828) •题意 给你 n 个矩形,求矩形并的周长: •题解1(两次扫描线) 周 ...
- Spring Security 学习笔记-授权控制过滤器
FilterSecurityInterceptor 是比较核心的过滤器,主要负责授权工作.SecurityMetadataSource 需要安全授权的元数据资源 AuthenticationMana ...
- H3C 递归查询
- linux 创建你的 /proc 文件
一旦你有一个定义好的 read_proc 函数, 你应当连接它到 /proc 层次中的一个入口项. 使用一个 creat_proc_read_entry 调用: struct proc_dir_ent ...
- 常见DOS操作
D: 去往D盘 cd.. 返回上一级目录 cd 文件名 目录切换到该文件名(子目录)下 cd \ 直接回根目录 dir 当前根目录下的文件目录 dir /s 所有目录