codevs3981动态最大子段和(线段树)
2024-09-08 07:24:14
3981 动态最大子段和
时间限制: 1 s
空间限制: 128000 KB
题目等级 : 钻石 Diamond
题目描述 Description
题目还是简单一点好...
有n个数,a[1]到a[n]。
接下来q次查询,每次动态指定两个数l,r,求a[l]到a[r]的最大子段和。
子段的意思是连续非空区间。
输入描述 Input Description
第一行一个数n。
第二行n个数a[1]~a[n]。
第三行一个数q。
以下q行每行两个数l和r。
输出描述 Output Description
q行,每行一个数,表示a[l]到a[r]的最大子段和。
样例输入 Sample Input
7
2 3 -233 233 -23 -2 233
4
1 7
5 6
2 5
2 3
样例输出 Sample Output
441
-2
233
3
数据范围及提示 Data Size & Hint
对于50%的数据,q*n<=10000000。
对于100%的数据,1<=n<=200000,1<=q<=200000。
a[1]~a[n]在int范围内,但是答案可能超出int范围。
数据保证1<=l<=r<=n。
空间128M,时间1s。
我不会告诉你数据里有样例
/*
线段树区间操作GSS
一段长的区间的 GSS 有三种情况:
1 完全在左子区间
2 完全在右子区间
3 横跨左右区间
前两种情况可使用子区间的 GSS,但如何处理第三种情况?
注意到我们可以把区间拆成两部分,这两部分是不相关的。
所以我们需要维护一个区间的“最大左子段和”和“最大右子段和”。
gss = MAX{l.gss,r.gss,l.rgss + r.lgss}
由 GSS 一直推下来,对于每个节点,我们一共需要设计4个状态。
1 GSS:最大子段和
2 LGSS:最大左子段和
3 RGSS:最大右子段和
4 SUM:整段和
这里我用了结构体存储(元元真厉害啊!)
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
#define maxn 2000010 using namespace std;
ll n,a[maxn],q,x,y,ans;
struct node{
ll l,r,dis,mx,lmx,rmx;
}tre[maxn>>]; ll init()
{
ll x=,f=;char c=getchar();
while(c>''||c<''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
} void build(int now,ll l,ll r)
{
tre[now].l=l;tre[now].r=r;
if(l==r)
{
tre[now].dis=init();
tre[now].lmx=tre[now].rmx=tre[now].mx=tre[now].dis;
return ;
}
ll mid=(l+r)>>;
build(now<<,l,mid);
build(now<<|,mid+,r);
//下面是重点之一,要注意。
tre[now].lmx=max(tre[now<<].lmx,tre[now<<].dis+tre[now<<|].lmx);
tre[now].rmx=max(tre[now<<|].rmx,tre[now<<|].dis+tre[now<<].rmx);
tre[now].mx=max(tre[now<<].rmx+tre[now<<|].lmx,max(tre[now<<].mx,tre[now<<|].mx));
tre[now].dis=tre[now<<].dis+tre[now<<|].dis;
} node query(int now,ll l,ll r)
{
node ans;
if(l==tre[now].l&&r==tre[now].r) return tre[now];
ll mid=(tre[now].l+tre[now].r)>>;
if(l>mid) return query(now<<|,l,r);
else if(r<=mid) return query(now<<,l,r);
else//就是这里咋也不会写,递归找边界思路不清晰
{
node lch=query(now<<,l,mid);
node rch=query(now<<|,mid+,r);
ans.lmx=max(lch.lmx,lch.dis+rch.lmx);
ans.rmx=max(rch.rmx,rch.dis+lch.rmx);
ans.mx=max(max(lch.mx,rch.mx),lch.rmx+rch.lmx);
}
return ans;
}
int main()
{
n=init();
build(,,n);
q=init();
for(int i=;i<=q;i++)
{
x=init();y=init();
printf("%lld\n",query(,x,y).mx);
}
return ;
}
最新文章
- RequireJS基础(三)
- 轻松玩转jquery。
- 云计算之路-阿里云上:RDS用户的烦恼
- Spring利用JDBCTemplate实现批量插入和返回id
- scp 使用
- dfs介绍
- backbone前端基础框架搭建
- hdu 4672 Present Day, Present Time 博弈论
- EffectiveC#5--始终提供ToString()
- 学习笔记-menusript控件中条目权限设置使用
- zookeeper资料
- java io系列18之 CharArrayReader(字符数组输入流)
- nodejs(二)浏览器与服务器连接初探
- 使用SatelliteMenu创建动画菜单
- ELK学习笔记之简单适用的ES集群监控工具cerebro安装使用
- psutil模块
- 环境安装问题:tensorflow 问题记录 python2.7 和 python3.6发生冲突
- BZOJ 2738 子矩阵第k大 | 二维树状数组 整体二分 分治
- [misc]printf/fprintf/sprintf/snprintf函数
- 获取代理服务器ip列表的方法
热门文章
- 诊断:ORA-38760: This database instance failed to turn on flashback database
- CSDN怎么转载别人的博客
- UVA - 10603 Fill(BFS求最小值问题)
- <;MySQL>;入门五 视图
- oracle打开或者关闭flashback
- Redis多实例配置以及主从同步
- 51nod 1096 距离之和最小 1108 距离之和最小 V2
- J - A Bug&#39;s Life 并查集
- python实现汉诺塔算法
- [转]C++回调函数(callback)的使用