题意
和 GSS1 一样,还是一个长度为 n 的序列和 m 个 querry,只不过这次 querry 的格式是 x1 y1 x2 y2,求 max{ a[i]+a[i+1]+...+a[j] }, x1<=i<=y1 x2<=j<=y2
做法分析
同 GSS1 一样,只不过查询的时候需分类讨论:
1、y1<x2:那么 [y1, x2] 这一段的数必取,再选择性的加上 Lmax[x1, y1-1] Rmax[x2+1, y2] 即可
2、y1>=x2:把整个 i 和 j 的取值分为三类讨论:
(1)、x1<=i<=x2, x2<=j<=y2:val[x2]+Rmax[x1, x2-1]+Lmax[x2+1, y2]
(2)、x2<=i<=y1, y1<=j<=y2:val[y1]+Rmax[x1, y1-1]+Lmax[y1+1, y2]
(3)、x2<=i<=j<=y1:Max[x1, y1]
取三种情况中最大的即可
参考代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
const int N=10010;
const int INT_INF=0x3fffffff;
int val[N];
class seg_tree
{
private:
struct data
{
int st, en, val, Max, Lmax, Rmax;
} T[N<<2];
public:
data update(data Lson, data Rson)
{
data fa;
fa.Lmax=max(Lson.Lmax, Lson.val+Rson.Lmax);
fa.Rmax=max(Rson.Rmax, Rson.val+Lson.Rmax);
fa.Max=max(max(Lson.Max, Rson.Max), Lson.Rmax+Rson.Lmax);
fa.val=Lson.val+Rson.val;
return fa;
}
void build(int id, int st, int en)
{
T[id].st=st, T[id].en=en;
if(st==en)
{
T[id].val=T[id].Max=T[id].Lmax=T[id].Rmax=val[st];
return;
}
int mid=(st+en)>>1;
build(id<<1, st, mid), build(id<<1|1, mid+1, en);
data now=update(T[id<<1], T[id<<1|1]);
T[id].val=now.val, T[id].Max=now.Max, T[id].Lmax=now.Lmax, T[id].Rmax=now.Rmax;
}
data query(int id, int L, int R)
{
if(L<=T[id].st && T[id].en<=R)
{
return T[id];
}
int mid=(T[id].st+T[id].en)>>1;
if(R<=mid) return query(id<<1, L, R);
else if(L>mid) return query(id<<1|1, L, R);
else return update(query(id<<1, L, mid), query(id<<1|1, mid+1, R));
}
} seg;
int main()
{
int t; scanf("%d", &t);
while(t--)
{
int n; scanf("%d", &n);
for(int i=1; i<=n; i++)
scanf("%d", &val[i]);
seg.build(1, 1, n);
int m; scanf("%d", &m);
for(int i=1, x1, y1, x2, y2; i<=m; i++)
{
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
if(y1<x2)
{
int ans=seg.query(1, y1, x2).val;
if(x1<=y1-1) ans+=max(0, seg.query(1, x1, y1-1).Rmax);
if(x2+1<=y2) ans+=max(0, seg.query(1, x2+1, y2).Lmax);
printf("%d\n", ans);
}
else
{
int ans1=val[x2];
if(x1<=x2-1) ans1+=max(0, seg.query(1, x1, x2-1).Rmax);
if(x2+1<=y2) ans1+=max(0, seg.query(1, x2+1, y2).Lmax);
int ans2=val[y1];
if(x1<=y1-1) ans2+=max(0, seg.query(1, x1, y1-1).Rmax);
if(y1+1<=y2) ans2+=max(0, seg.query(1, y1+1, y2).Lmax);
int ans3=seg.query(1, x2, y1).Max;
printf("%d\n", max(ans1, max(ans2, ans3)));
}
}
}
return 0;
}