前言

最近沉迷于数据结构,感觉数据结构很有意思。

正文

分析

先来分类讨论一下

1. \(x2<y1\)

如果 \(y1<x2\) 的话,答案 \(=\max \limits_{ y1 \leq x \leq y2} \{ s_i \} - \min \limits_{x1 \leq x \leq x2} \{ s_i \}\)

其中 \(s_i\) 表示 \(\sum\limits_{j=1}^{i} a_j\) ,就是俗称的前缀和

这个东西可以用线段树维护。

2. \(x2>=y1\)

这个怎么处理呢

答案 \(=\) \(\max \begin{cases}\max \limits_{ y1 \leq x \leq y2} \{ s_i \} - \min \limits_{x1 \leq x \leq y1} \{ s_i \}\\ \max \limits_{ x2 \leq x \leq y2} \{ s_i \} - \min \limits_{x1 \leq x \leq x2} \{ s_i \}\\ f(x,y)\end{cases}\)

这里的 \(f\) 函数就是最大子段和。

不会用线段树求最大子段和的可以看这里

最上面的 \(2\) 个也是可以用线段树来维护的。

代码

最后要注意的一点是前缀和,我们知道区间 \([i,j]\) 的和 $ = s_j-s_{i-1}$,而不是 $ = s_j-s_{i}$

这个怎么处理呢,我们发现我们的题目全部都是用 \(Max\) 函数的答案减去 \(Min\) 函数的答案,所以,我们可以把线段树维护的 \(\min\) 全部减去 \(a_{i}\)

现在这份代码就能 \(A\) 了

#include <bits/stdc++.h>
#define ls num<<1
#define rs num<<1|1
using namespace std;
typedef long long ll;
template<typename T>inline void read(T &FF){
T RR=1;FF=0;char CH=getchar();
for(;!isdigit(CH);CH=getchar())if(CH=='-')RR=-1;
for(;isdigit(CH);CH=getchar())FF=(FF<<1)+(FF<<3)+(CH^48);
FF*=RR;
}
template<typename T>void write(T x){
if(x<0)putchar('-'),x*=-1;
if(x>9)write(x/10);
putchar(x%10+48);
}
template<typename T>void writen(T x){
write(x);
puts("");
}
const int MAXN=5e4+10;
struct Tree{
int l,r;
ll lans,rans,sum,ans,max,min;
}t[MAXN*4];
int a[MAXN],x,y,n,T,T_,l1,r1,l2,r2;
ll s[MAXN];
Tree pushup(Tree L,Tree R){
Tree z;
z.sum=L.sum+R.sum;
z.lans=max(L.lans,L.sum+R.lans);
z.rans=max(R.rans,R.sum+L.rans);
z.ans=max(max(L.ans,R.ans),L.rans+R.lans);
z.max=max(L.max,R.max);
z.min=min(L.min,R.min);
z.l=L.l;z.r=R.r;
return z;
}
void build(int l,int r,int num){
if(l==r){
t[num].l=l;
t[num].r=r;
t[num].sum=a[l];
t[num].lans=a[l];
t[num].rans=a[l];
t[num].ans=a[l];
t[num].max=s[l];
t[num].min=s[l]-a[l];
return;
}
int mid=(l+r)>>1;
build(l,mid,ls);
build(mid+1,r,rs);
t[num]=pushup(t[ls],t[rs]);
}
Tree query(int num){
if(x<=t[num].l&&t[num].r<=y)return t[num];
if(t[rs].l>y)return query(ls);
if(t[ls].r<x)return query(rs);
return pushup(query(ls),query(rs));
}
ll Max(int num){
if(t[num].l>=x&&t[num].r<=y)return t[num].max;
if(t[ls].r<x)return Max(rs);
if(t[rs].l>y)return Max(ls);
return max(Max(ls),Max(rs));
}
ll Min(int num){
if(t[num].l>=x&&t[num].r<=y)return t[num].min;
if(t[ls].r<x)return Min(rs);
if(t[rs].l>y)return Min(ls);
return min(Min(ls),Min(rs));
}
ll Mx(int a,int b){
x=a;y=b;
return Max(1);
}
ll Mn(int a,int b){
x=a;y=b;
return Min(1);
}
ll qy(int a,int b){
x=a;y=b;
return query(1).ans;
}
int main(){
read(T);
while(T--){
read(n);
for(int i=1;i<=n;i++)read(a[i]);
for(int i=1;i<=n;i++)s[i]=s[i-1]+a[i];
build(1,n,1);
read(T_);
while(T_--){
read(l1);read(r1);read(l2);read(r2);
if(r1>l2)writen(max(qy(l2,r1),max(Mx(l2,r2)-Mn(l1,l2),Mx(r1,r2)-Mn(l1,r1))));
else writen(Mx(l2,r2)-Mn(l1,r1));
}
}
return 0;
}

后记

这篇题解如果有问题可以私信或评论,告诉我,一起完善

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

  1. 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$,但是不保证端点所在的区间不重合 ...

  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. [题解] SPOJ GSS1 - Can you answer these queries I

    [题解] SPOJ GSS1 - Can you answer these queries I · 题目大意 要求维护一段长度为 \(n\) 的静态序列的区间最大子段和. 有 \(m\) 次询问,每次 ...

  9. 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 ...

随机推荐

  1. GDB调试指南-单步调试

    前言 前面通过<启动调试>,<断点设置>,<变量查看>,我们已经了解了GDB基本的启动,设置断点,查看变量等,如果这些内容你还不知道,建议先回顾一下前面的内容.在启 ...

  2. JavaScript是如何工作的(一)

    简评:JavaScript 是越来越受欢迎了,很多团队都在采用这些语言工作.前端.后端.嵌入式设备等等,都可以看见它的身影.虽然我们知其然,但又知其所以然吗? 大家应该都知道 JavaScript 是 ...

  3. 选题在线提交系统(html+JS+php)

    前言:         作为学习委员还是有挺多的事情要忙的,比如经常统计同学们的课设题目选择结果.如果老师的要求少一点,我还可以轻松一点.但是当老师对选题有种种限制的时候,自己就估计不会那么好办了.这 ...

  4. jenkins-设置定时任务

    前言 跑自动化用例每次用手工点击 jenkins 出发自动化用例太麻烦了,我们希望能每天固定时间 跑,这样就不用管了,坐等收测试报告结果就行. 一.定时构建语法  * * * * * (五颗星,中间用 ...

  5. 达拉草201771010105《面向对象程序设计(java)》第十七周学习总结

    达拉草201771010105<面向对象程序设计(java)>第十七周学习总结 第一部分:理论知识 1.多线程的概念: (1)多线程是进程执行过程中产生的多条执行线索. (2)多线程意味着 ...

  6. 达拉草201771010105《面向对象程序设计(java)》第十四周学习总结

    达拉草201771010105<面向对象程序设计(java)>第十四周学习总结 第一部分:理论知识 布局管理器: 布局管理器是一组类. 实现java.awt.LayoutManager接口 ...

  7. 强大的java工作流引擎,可视化开发工作流

    我们先来看看什么是工作流? 所谓工作流引擎是指workflow作为应用系统的一部分,并为之提供对各应用系统有决定作用的根据角色.分工和条件的不同决定信息传递路由.内容等级等核心解决方案.工作流引擎包括 ...

  8. js获取当前日期是一年中的第几天

    js获取当前日期为一年中的第几天 const currentYear = new Date().getFullYear().toString(); // 今天减今年的第一天(xxxx年01月01日) ...

  9. 一些大厂的css reset 代码

    不同的浏览器对标签的默认值不同,为了避免页面出现浏览器差异,所以要初始化样式表属性.使用通配符*并不可取,因为会遍历到每一个标签,大型网页会加载过慢,影响性能. 雅虎工程师提供的CSS初始化示例代码: ...

  10. NetAnalyzer笔记 之 十一 打造自己的协议分析语言(1)初衷与语法构想

    回头看看NetAnalyzer开发系文档上次一篇竟然是2016年,老脸一红.不过这几年墨云成功过的讨到一个温柔贤淑的老婆,有了一个幸福的家庭,去年9月又有了一个大胖儿子,想想也就释然了^_^ 其实这几 ...