题目描述 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。
一、一个区间的最大子段和有三种情况
1、左子区间的最大子段和
2、右子区间的最大子段和
3、横跨左右子区间
二、每个结点需要维护的信息
1、区间和sum
2、从区间左端点开始的最大子段和lgss
3、从区间右端点开始的最大子段和rgss
4、区间最大子段和gss
三、建树
1、遇到叶子节点就输入数据
2、合并区间信息
sum:左右子区间的区间和相加
lgss:max(左子区间的lgss,左子区间的sum + 右子区间的lgss)
rgss:max(右子区间的rgss,右子区间的sum + 左子区间的rgss)
gss:max(max(左子区间的最大子段和,右子区间的最大子段和),左子区间的右起最大子段和 + 右子区间的左起最大子段和)
四、查询
1、查询区间完全包含于搜索区间:更新ans和pre
pre:前一个搜索区间的从右端点开始的最大子段和(起连接左右两个区间的作用)
ans:到目前为止的最大子段和
ans的更新:要么就是该搜索区间的最大子段和,要么跨区间(跨区间即pre+当前搜索区间的lgss)
pre的更新:pre+该区间的sum 或 该区间的rgss
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const long long INF = 0x7FFFFFFFFFFFFFFF;
int n,q,a,b;
long long ans,pre;
struct node
{
int l,r;
long long gss,lgss,rgss,sum;
}tree[800001];
void Merge(int k)
{
tree[k].gss = max(max