给定一个序列。查询左端点在$[x_1, y_1]$之间,且右端点在$[x_2, y_2]$之间的最大子段和,数据保证$x_1leq x_2,y_1leq y_2$,但是不保证端点所在的区间不重合
这题可以分为几种情况讨论
$y_1<x_2$
那么这个时候发现$[y_1+1,x_2-1]$里的数必须得选,并选出$[x1,y1]$的最大后缀和$[x2,y2]$的最大前缀。用结构体维护一下就好了
$y_1geq x_2$
发现这个时候左右端点所在区间的情况分别如下
$l$在$[x_1,x_2]$,$r$在$[x_2,y_1]$,那么只要查询$[x_1,x_2]$的最大后缀和$[x_2,y_1]$的最大前缀
$l$在$[x_1,x_2]$,$r$在$[y_1,y_2]$,那么只要查询$[x_1,x_2]$的最大后缀和$[x_2,y_2]$的最大前缀
$l$在$[x_2,y_1]$,$r$在$[x_2,y_1]$,那么只要查询$[x_2,y_1]$的最大子段和
$l$在$[x_2,y_1]$,$r$在$[y_1,y_2]$,那么只要查询$[x_2,y_1]$的最大后缀和$[y_1,y_2]$的最大前缀
1 //minamoto 2 #include<iostream> 3 #include<cstdio> 4 #include<algorithm> 5 #define ls (p<<1) 6 #define rs (p<<1|1) 7 using namespace std; 8 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) 9 char buf[1<<21],*p1=buf,*p2=buf; 10 template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;} 11 int read(){ 12 #define num ch-'0' 13 char ch;bool flag=0;int res; 14 while(!isdigit(ch=getc())) 15 (ch=='-')&&(flag=true); 16 for(res=num;isdigit(ch=getc());res=res*10+num); 17 (flag)&&(res=-res); 18 #undef num 19 return res; 20 } 21 char sr[1<<21],z[20];int C=-1,Z; 22 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;} 23 void print(int x){ 24 if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x; 25 while(z[++Z]=x%10+48,x/=10); 26 while(sr[++C]=z[Z],--Z);sr[++C]=' '; 27 } 28 const int N=1e4+5;int a[N],n,m; 29 struct node{int pre,mid,suf,sum;}b[N<<2]; 30 node merge(node l,node r){ 31 node ans; 32 ans.pre=max(l.pre,l.sum+r.pre); 33 ans.mid=max(max(l.mid,r.mid),l.suf+r.pre); 34 ans.suf=max(l.suf+r.sum,r.suf); 35 ans.sum=l.sum+r.sum; 36 return ans; 37 } 38 void upd(int p){b[p]=merge(b[ls],b[rs]);} 39 void build(int p,int l,int r){ 40 if(l==r) return (void)(b[p].pre=b[p].mid=b[p].suf=b[p].sum=a[l]); 41 int mid=(l+r)>>1; 42 build(ls,l,mid),build(rs,mid+1,r); 43 upd(p); 44 } 45 node query(int p,int l,int r,int ql,int qr){ 46 if(ql>qr) return (node){0,0,0,0}; 47 if(ql<=l&&qr>=r) return b[p]; 48 int mid=(l+r)>>1; 49 if(qr<=mid) return query(ls,l,mid,ql,qr); 50 else if(ql>mid) return query(rs,mid+1,r,ql,qr); 51 else return merge(query(ls,l,mid,ql,qr),query(rs,mid+1,r,ql,qr)); 52 } 53 int get(int l1,int r1,int l2,int r2){ 54 if(r1<l2){ 55 int tmp=query(1,1,n,l1,r1).suf; 56 tmp+=query(1,1,n,r1+1,l2-1).sum; 57 tmp+=query(1,1,n,l2,r2).pre; 58 return tmp; 59 } 60 int ans=query(1,1,n,l2,r1).mid; 61 if(l1<l2) cmax(ans,query(1,1,n,l1,l2).suf+query(1,1,n,l2,r2).pre-a[l2]); 62 if(r2>r1) cmax(ans,query(1,1,n,l1,r1).suf+query(1,1,n,r1,r2).pre-a[r1]); 63 return ans; 64 } 65 int main(){ 66 // freopen("testdata.in","r",stdin); 67 int T=read(); 68 while(T--){ 69 n=read(); 70 for(int i=1;i<=n;++i) a[i]=read(); 71 build(1,1,n); 72 m=read(); 73 while(m--){ 74 int l1=read(),r1=read(),l2=read(),r2=read(); 75 print(get(l1,r1,l2,r2)); 76 } 77 } 78 return Ot(),0; 79 }