给定一个序列。查询左端点在$[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]$的最大前缀

 //minamoto
#include<iostream>
#include<cstdio>
#include<algorithm>
#define ls (p<<1)
#define rs (p<<1|1)
using namespace std;
#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[<<],*p1=buf,*p2=buf;
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,:;}
int read(){
#define num ch-'0'
char ch;bool flag=;int res;
while(!isdigit(ch=getc()))
(ch=='-')&&(flag=true);
for(res=num;isdigit(ch=getc());res=res*+num);
(flag)&&(res=-res);
#undef num
return res;
}
char sr[<<],z[];int C=-,Z;
inline void Ot(){fwrite(sr,,C+,stdout),C=-;}
void print(int x){
if(C><<)Ot();if(x<)sr[++C]=,x=-x;
while(z[++Z]=x%+,x/=);
while(sr[++C]=z[Z],--Z);sr[++C]='\n';
}
const int N=1e4+;int a[N],n,m;
struct node{int pre,mid,suf,sum;}b[N<<];
node merge(node l,node r){
node ans;
ans.pre=max(l.pre,l.sum+r.pre);
ans.mid=max(max(l.mid,r.mid),l.suf+r.pre);
ans.suf=max(l.suf+r.sum,r.suf);
ans.sum=l.sum+r.sum;
return ans;
}
void upd(int p){b[p]=merge(b[ls],b[rs]);}
void build(int p,int l,int r){
if(l==r) return (void)(b[p].pre=b[p].mid=b[p].suf=b[p].sum=a[l]);
int mid=(l+r)>>;
build(ls,l,mid),build(rs,mid+,r);
upd(p);
}
node query(int p,int l,int r,int ql,int qr){
if(ql>qr) return (node){,,,};
if(ql<=l&&qr>=r) return b[p];
int mid=(l+r)>>;
if(qr<=mid) return query(ls,l,mid,ql,qr);
else if(ql>mid) return query(rs,mid+,r,ql,qr);
else return merge(query(ls,l,mid,ql,qr),query(rs,mid+,r,ql,qr));
}
int get(int l1,int r1,int l2,int r2){
if(r1<l2){
int tmp=query(,,n,l1,r1).suf;
tmp+=query(,,n,r1+,l2-).sum;
tmp+=query(,,n,l2,r2).pre;
return tmp;
}
int ans=query(,,n,l2,r1).mid;
if(l1<l2) cmax(ans,query(,,n,l1,l2).suf+query(,,n,l2,r2).pre-a[l2]);
if(r2>r1) cmax(ans,query(,,n,l1,r1).suf+query(,,n,r1,r2).pre-a[r1]);
return ans;
}
int main(){
// freopen("testdata.in","r",stdin);
int T=read();
while(T--){
n=read();
for(int i=;i<=n;++i) a[i]=read();
build(,,n);
m=read();
while(m--){
int l1=read(),r1=read(),l2=read(),r2=read();
print(get(l1,r1,l2,r2));
}
}
return Ot(),;
}

SP2916 GSS5 - Can you answer these queries V的更多相关文章

  1. 题解 SP2916 【GSS5 - Can you answer these queries V】

    前言 最近沉迷于数据结构,感觉数据结构很有意思. 正文 分析 先来分类讨论一下 1. \(x2<y1\) 如果 \(y1<x2\) 的话,答案 \(=\max \limits_{ y1 \ ...

  2. SPOJ GSS5 Can you answer these queries V

    Time Limit: 132MS   Memory Limit: 1572864KB   64bit IO Format: %lld & %llu Description You are g ...

  3. 【SP2916】Can you answer these queries V - 线段树

    题面 You are given a sequence \(a_1,a_2,...,a_n\). (\(|A[i]| \leq 10000 , 1 \leq N \leq 10000\)). A qu ...

  4. SPOJ GSS5 Can you answer these queries V ——线段树

    [题目分析] GSS1上增加区间左右端点的限制. 直接分类讨论就好了. [代码] #include <cstdio> #include <cstring> #include & ...

  5. [GSS5] Can you answer these queries V

    大力讨论. luogu上交spoj的题卡的一比... 难受 wa了好几次,原因大概首先求的是非空区间,不能乱和0取max,第二点是求无相交的解时,在两段求lmx和rmx的时候可以取max(0). 区间 ...

  6. SPOJ 2916 GSS5 - Can you answer these queries V

    传送门 解题思路 和GSS1相似,但需要巨恶心的分类讨论,对于x1<=y1< x2< =y2 这种情况 , 最大值应该取[x1,y1]的右端最大+[y1+1,x2-1]的和+[x2, ...

  7. GSS5 spoj 2916. Can you answer these queries V 线段树

    gss5 Can you answer these queries V 给出数列a1...an,询问时给出: Query(x1,y1,x2,y2) = Max { A[i]+A[i+1]+...+A[ ...

  8. Can you answer these queries V SPOJ - GSS5 (分类讨论+线段树维护区间最大子段和)

    recursion有一个整数序列a[n].现在recursion有m次询问,每次她想知道Max { A[i]+A[i+1]+...+A[j] ; x1 <= i <= y1 , x2 &l ...

  9. SPOJ 2916 Can you answer these queries V(线段树-分类讨论)

    题目链接:http://www.spoj.com/problems/GSS5/ 题意:给出一个数列.每次查询最大子段和Sum[i,j],其中i和j满足x1<=i<=y1,x2<=j& ...

随机推荐

  1. Qt笔记——各种组件和其他细碎用法

    LineEdit 获取文本:ui->usrLineEdit->text() 清空内容:ui->pwdLineEdit->clear(); 定位光标:ui->usrLine ...

  2. Ubuntu中Hadoop环境搭建

    Ubuntu中Hadoop环境搭建 JDK安装 方法一:通过命令行直接安装(不建议) 有两种java可以安装oracle-java8-installer以及openjdk (1)安装oracle-ja ...

  3. Android BGABadgeView:显示提示数字(2)

     Android BGABadgeView:显示提示数字(2) 在附录文章3的基础上,对代码进行稍微改造,显示在红色小圆球内部显示数字,同时给红色小圆球通过可编程调控红色小圆球的整体外观,布局文件 ...

  4. hihocoder #1034 : 毁灭者问题 平衡树(set)+线段树

    #1034 : 毁灭者问题 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在 Warcraft III 之冰封王座中,毁灭者是不死族打三本后期时的一个魔法飞行单位. 毁 ...

  5. [NOIP2008] 提高组 洛谷P1149 火柴棒等式

    题目描述 给你n根火柴棍,你可以拼出多少个形如“A+B=C”的等式?等式中的A.B.C是用火柴棍拼出的整数(若该数非零,则最高位不能是0).用火柴棍拼数字0-9的拼法如图所示: 注意: 加号与等号各自 ...

  6. Linux下汇编语言学习笔记2 ---

    这是17年暑假学习Linux汇编语言的笔记记录,参考书目为清华大学出版社 Jeff Duntemann著 梁晓辉译<汇编语言基于Linux环境>的书,喜欢看原版书的同学可以看<Ass ...

  7. poj - 3041 Asteroids (二分图最大匹配+匈牙利算法)

    http://poj.org/problem?id=3041 在n*n的网格中有K颗小行星,小行星i的位置是(Ri,Ci),现在有一个强有力的武器能够用一发光速将一整行或一整列的小行星轰为灰烬,想要利 ...

  8. codeforces 691D(数据结构)

    D. Swaps in Permutation time limit per test 5 seconds memory limit per test 256 megabytes input stan ...

  9. rsyslog trouble shooting

    openstack,swift的log不输出了.trouble shooting过程 , 发现我们的程序 /var/log/swift/proxy.log等总是不输出log. 因为log rsyslo ...

  10. nyist oj 19 擅长排列的小明(dfs搜索+STL)

    擅长排列的小明 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描写叙述 小明十分聪明.并且十分擅长排列计算.比方给小明一个数字5,他能立马给出1-5按字典序的全排列,假设你想 ...