给定一个序列。查询左端点在$[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. STM32F407 GPIO原理 个人笔记

    datasheet(STM32F407ZGT6.pdf)中,IO structure 为FT,表示容忍5V电压 后面的uart1_TX之类,表示端口复用 共有A~G7组IO口, 每组16个IO口:0~ ...

  2. Python 循环语句(break和continue)

    Python 循环语句(break和continue) while 语句时还有另外两个重要的命令 continue,break 来跳过循环,continue 用于跳过该次循环,break 则是用于退出 ...

  3. xtu read problem training 4 A - Moving Tables

    Moving Tables Time Limit: 2000ms Memory Limit: 65536KB This problem will be judged on ZJU. Original ...

  4. [ZJOI2010] 数字统计

    [ZJOI2010] 数字统计 题目 给定两个正整数a和b,求在[a,b]中的所有整数中,每个数码(digit)各出现了多少次. INPUT 输入文件中仅包含一行两个整数a.b,含义如上所述 OUTP ...

  5. hihoCoder#1036 Trie图

    原题地址 看了这篇博文,总算是把Trie图弄明白了 Runtime Error了无数次,一直不知道为什么,于是写了个脚本生成了一组大数据,发现果然段错误了. 调试了一下午,总算闹明白了,为什么呢? 1 ...

  6. HDU 4473

    题目大意: 给定一个long long 型的数 n,找到一共有多少对a,b,使比n小的某一个数的是a*b的倍数 这样我们可以理解为 存在a*b*c <= n,令 a <= b <= ...

  7. [luoguP1272] 重建道路

    传送门 奇奇怪怪的分组背包. #include <cstdio> #include <cstring> #include <iostream> #define N ...

  8. 共享一个NOI用过的vimrc [rc][vimrc]

    set nocp set nu set ru set noet set ai set cin set mouse =a set mp=g++\ %\ -o\ %<\ -g\ -Wall\ -Ws ...

  9. Linux下汇编语言学习笔记26 ---

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

  10. Spring Boot - how to configure port

    https://stackoverflow.com/questions/21083170/spring-boot-how-to-configure-port