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);
}
}