Time limit: 0.132s $ \quad $ Source limit: 50000B $ \quad $ Memory limit:1536MB
You are given a sequence A[1], A[2], ..., A[N] . ( |A[i]| <= 10000 , 1 <= N <= 10000 ).
A query is defined as follows:
Query(x1,y1,x2,y2) = Max { A[i]+A[i+1]+...+A[j] ; x1 <= i <= y1 , x2 <= j <= y2 and x1 <= x2 , y1 <= y2 }.
Given M queries (1 <= M <= 10000), your program must output the results of these queries.
Input
The first line of the input consist of the number of tests cases <= 5. Each case consist of the integer N and the sequence A.
Then the integer M. M lines follow, contains 4 numbers x1, y1, x2 y2.
Output
Your program should output the results of the M queries for each test case, one query per line.
Examples
Input:
2
6 3 -2 1 -4 5 2
2
1 1 2 3
1 3 2 5
1 1
1
1 1 1 1
Output:
2
3
1
题意翻译
给定一个序列。查询左端点在 $ [x_1, y_1] $ 之间,且右端点在 $ [x_2, y_2] $ 之间的最大子段和,
数据保证 $ x_1\leq x_2,y_1\leq y_2 $ ,但是不保证端点所在的区间不重合
感谢@Anoxiacxy 提供的翻译
思路
如果 $ x_1 \le y_1 <x_2 \le y_2 $
-
- 区间分离,中间必须取,两端区间靠近中间选最大
- 区间分离,中间必须取,两端区间靠近中间选最大
如果 $ x_1 \le x_2 \le y_1 \le y_2 $
-
- 选取 $ [x_2,y_1] $ 中的最大子段和
选取 $ [x_1,x_2-1] $ 的最右端部分,和 $ [x_2,y_1] $ 的最左端部分
选取 $ [x_2,y_1] $ 的最右端部分,和 $ [y_1+1,y_2] $ 的最左端部分
选取 $ [x_1,x_2-1] $ 的最右端部分,$ [x_2,y_1] $ 的全部,和 $ [y_1+1,y_2] $ 的最左端部分
- 选取 $ [x_2,y_1] $ 中的最大子段和
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 100010
#define int long long
struct tree{ int l,r,lmax,rmax,max,sum; }t[maxn<<2];
int T,n,m,x1,x2,y1,y2,s[maxn],ans;
void pushup(int o){
t[o].sum=t[o<<1].sum+t[o<<1|1].sum;
t[o].lmax=max(t[o<<1].sum+t[o<<1|1].lmax,t[o<<1].lmax);
t[o].rmax=max(t[o<<1|1].sum+t[o<<1].rmax,t[o<<1|1].rmax);
t[o].max=max(t[o<<1].rmax+t[o<<1|1].lmax,max(t[o<<1].max,t[o<<1|1].max));
}
void build(int o,int l,int r){
t[o].l=l; t[o].r=r;
if(l==r){
scanf("%lld",&t[o].sum);
s[l]=s[l-1]+t[o].sum;
t[o].max=t[o].lmax=t[o].rmax=t[o].sum;
return;
}
int mid=l+r>>1;
build(o<<1,l,mid); build(o<<1|1,mid+1,r);
pushup(o);
}
int ql(int o,int l,int r){
if(l>r) return 0;
if(t[o].l==l&&t[o].r==r) return t[o].lmax;
int mid=t[o].l+t[o].r>>1;
if(l>mid) return ql(o<<1|1,l,r);
else if(r<=mid) return ql(o<<1,l,r);
else return max(ql(o<<1,l,mid),s[mid]-s[l-1]+ql(o<<1|1,mid+1,r));
}
int qr(int o,int l,int r){
if(l>r) return 0;
if(t[o].l==l&&t[o].r==r) return t[o].rmax;
int mid=t[o].l+t[o].r>>1;
if(l>mid) return qr(o<<1|1,l,r);
else if(r<=mid) return qr(o<<1,l,r);
else return max(qr(o<<1|1,mid+1,r),s[r]-s[mid]+qr(o<<1,l,mid));
}
int qm(int o,int l,int r){
if(l>r) return 0;
if(t[o].l==l&&t[o].r==r) return t[o].max;
int mid=t[o].l+t[o].r>>1;
if(l>mid) return qm(o<<1|1,l,r);
else if(r<=mid) return qm(o<<1,l,r);
else {
int Lmax=ql(o<<1|1,mid+1,r);
int Rmax=qr(o<<1,l,mid);
return max(Lmax+Rmax,max(qm(o<<1,l,mid),qm(o<<1|1,mid+1,r)));
}
}
signed main(){
scanf("%lld",&T);
while(T--){
scanf("%lld",&n);
build(1,1,n);
scanf("%lld",&m);
while(m--){
scanf("%lld %lld %lld %lld",&x1,&y1,&x2,&y2);
if(x2>y1){
ans=s[x2-1]-s[y1];
ans+=qr(1,x1,y1)+ql(1,x2,y2);
printf("%lld\n",ans);
} else {
ans=qm(1,x2,y1);
ans=max(ans,qr(1,x2,y1)+ql(1,y1+1,y2));
ans=max(ans,ql(1,x2,y1)+qr(1,x1,x2-1));
ans=max(ans,qr(1,x1,x2-1)+s[y1]-s[x2-1]+ql(1,y1+1,y2));
printf("%lld\n",ans);
}
}
}
return 0;
}