SP2916 GSS5 - Can you answer these queries V

给定一个序列。查询左端点在$[x_1, y_1]$之间,且右端点在$[x_2, y_2]$之间的最大子段和,数据保证$x_1\leq x_2,y_1\leq y_2$,但是不保证端点所在的区间不重合

 

这题可以分为几种情况讨论

$y_1<x_2$

那么这个时候发现$[y_1+1,x_2-1]$里的数必须得选,并选出$[x1,y1]$的最大后缀和$[x2,y2]$的最大前缀。用结构体维护一下就好了

$y_1\geq 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]='\n';
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 }

 

posted @ 2018-10-21 20:00  bztMinamoto  阅读(181)  评论(0编辑  收藏  举报
Live2D