LINK
题目描述
给出了序列 A[1],A[2],…,A[N]A[1],A[2],…,A[N]A[1],A[2],…,A[N] 。 (a[i]≤15007,1≤N≤50000 a[i]≤15007,1≤N≤50000a[i]≤15007,1≤N≤50000 )。查询定义如下: 查询 (x,y)=max{a[i]+a[i+1]+…+a[j];x≤i≤j≤y}(x,y)=\max{a[i]+a[i+1]+…+a[j];x≤i≤j≤y}(x,y)=max{a[i]+a[i+1]+…+a[j];x≤i≤j≤y}。 给定MMM个查询,程序必须输出这些查询的结果。
输入输出格式
输入格式:
输入文件的第一行包含整数NNN。
在第二行,NNN个数字跟随。
第三行包含整数MMM。
M行跟在后面,其中第1行包含两个数字xix_ixi和yiy_iyi。
输出格式:
您的程序应该输出MMM查询的结果,每一行一个查询。
感谢@何高琛 提供的翻译
输入输出样例
输入 #1
3
-1 2 3
1
1 2
输出 #1
2
就是求最大子段和
以上出处
父节点的pre=MAX (左儿子的pre 或者左儿子的区间和+右儿子的pre)
莫名其妙被卡了n次甚至还卡bits/stdc++.h
需要 inline +quickread()
比较重要的就是query()的操作了
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
using namespace std;
const int N=50010;
int n;
struct node
{
int maxn,sum,suf,pre;
}t[N<<2];
inline int read() {
int x = 0, f = 1; char c = getchar();
while(!isdigit(c)) { if(c == '-') f = -1; c = getchar(); }
while(isdigit(c)) { x = x * 10 + c - '0'; c = getchar(); }
return x * f;
}
inline void up(int rt)
{
t[rt].sum=t[rt<<1|1].sum+t[rt<<1].sum;
t[rt].maxn=max(max(t[rt<<1|1].maxn,t[rt<<1].maxn),t[rt<<1].suf+t[rt<<1|1].pre);
t[rt].pre=max(t[rt<<1].pre,t[rt<<1].sum+t[rt<<1|1].pre);
t[rt].suf=max(t[rt<<1|1].suf,t[rt<<1|1].sum +t[rt<<1].suf);
}
inline void build(int l,int r,int rt)
{
if(l==r)
{
int a;a=read();
t[rt]=(node){a,a,a,a};
return ;
}
int mid=(l+r)>>1;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
up(rt);
}
inline node query(int L,int R,int l,int r,int rt)
{
if(l>=L&&r<=R) return t[rt];
int mid=(l+r)>>1;
if(R<=mid) return query(L,R,l,mid,rt<<1);
else if(L>mid) return query(L,R,mid+1,r,rt<<1|1);
else
{
node a,b,ans;
a=query(L,R,l,mid,rt<<1);
b=query(L,R,mid+1,r,rt<<1|1);
ans.sum=a.sum+b.sum;
ans.maxn=max(max(a.maxn,b.maxn),a.suf+b.pre);
ans.pre=max(a.pre,a.sum+b.pre);
ans.suf=max(b.suf,b.sum +a.suf);
return ans;
}
}
int main()
{
n=read();
build(1,n,1);
int m;m=read();
while(m--)
{
int l,r;l=read();r=read();
printf("%d\n",query(l,r,1,n,1).maxn);
}
}