题面

You are given a sequence \(a_1,a_2,...,a_n\). (\(|A[i]| \leq 10000 , 1 \leq N \leq 10000\)). A query is defined as follows: Query(x1,y1,x2,y2) = \(Max{a_i+a_{i+1}+...+a_j;x_1 \leq i \leq y_1 , x_2 \leq j \leq y_2}\) and \(x_1 \leq x_2 , y_1 \leq y_2\). Given \(m\) queries (\(1 \leq M \leq 10000\)), your program must output the results of these queries.

题意

求所有左右端点分别在区间 \([x_1,y_1]\) 与 \([x_2,y_2]\) 的区间的最大连续子段和的最大值

思路

1° 两个区间不相交



答案显然是左边区间的 rmax+中间不重叠部分的 sum+右边区间的 lmax,即:\([x_1,y_1].rmax+[y_1,x_2].sum+[x_2,y_2].lmax\)

2° 两个区间相交



答案就会有三种情况

·① 答案区间为区间相交部分,即:\([x_2,y_1].max\)

·② 答案区间的左端点在相交部分左部,取相交部分左边的 rmax 和剩下区间的 lmax,再减掉加了两次的左边相交节点

即:\([x_1,x_2].rmax+[x_2,y_2].lmax-a_{x_2}\)

·③ 答案区间的右端点在相交部分右部,取相交部分右边的 lmax 和剩下区间的 rmax,再减掉加了两次的右边相交节点

即:\([y_1,y_2].lmax+[x_1,y_1].rmax-a_{y_1}\)

代码

/************************************************
*Author : lrj124
*Created Time : 2019.09.27.21:55
*Mail : 1584634848@qq.com
*Problem : spoj2916
************************************************/
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn = 10000 + 10;
struct seg { int l,r,sum,max; } tree[maxn<<2];
int T,n,q,a[maxn];
inline void pushup(int root) {
tree[root].sum = tree[root<<1].sum+tree[root<<1|1].sum;
tree[root].l = max(tree[root<<1].l,tree[root<<1|1].l+tree[root<<1].sum);
tree[root].r = max(tree[root<<1|1].r,tree[root<<1].r+tree[root<<1|1].sum);
tree[root].max = max(tree[root<<1].r+tree[root<<1|1].l,max(tree[root<<1].max,tree[root<<1|1].max));
}
inline void build(int l,int r,int root) {
if (l == r) {
tree[root] = { a[l],a[l],a[l],a[l] };
return;
}
int mid = l+r>>1;
build(l,mid,root<<1);
build(mid+1,r,root<<1|1);
pushup(root);
}
inline seg query(int l,int r,int ql,int qr,int root) {
if (ql > qr) return {0,0,0,0};
if (ql <= l && r <= qr) return tree[root];
int mid = l+r>>1;
if (mid >= qr) return query(l,mid,ql,qr,root<<1);
if (ql > mid) return query(mid+1,r,ql,qr,root<<1|1);
seg lson = query(l,mid,ql,qr,root<<1),rson = query(mid+1,r,ql,qr,root<<1|1),ans;
ans = { max(lson.l,rson.l+lson.sum),max(rson.r,lson.r+rson.sum),rson.sum+lson.sum,max(lson.r+rson.l,max(lson.max,rson.max)) };
return ans;
}
inline int solve(int l1,int r1,int l2,int r2) {
if (r1 < l2) return query(1,n,l1,r1,1).r+query(1,n,r1+1,l2-1,1).sum+query(1,n,l2,r2,1).l;
int ans = query(1,n,l2,r1,1).max;
if (l1 < l2) ans = max(ans,query(1,n,l1,l2,1).r+query(1,n,l2,r2,1).l-a[l2]);
if (r2 > r1) ans = max(ans,query(1,n,l1,r1,1).r+query(1,n,r1,r2,1).l-a[r1]);
return ans;
}
int main() {
for (scanf("%d",&T);T--;) {
memset(tree,0,sizeof(tree));
scanf("%d",&n);
for (int i = 1;i <= n;i++) scanf("%d",&a[i]);
build(1,n,1);
for (scanf("%d",&q);q--;) {
int l1,r1,l2,r2; scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
printf("%d\n",solve(l1,r1,l2,r2));
}
}
return 0;
}

【SP2916】Can you answer these queries V - 线段树的更多相关文章

  1. 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[ ...

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

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

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

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

  4. SPOJ GSS1_Can you answer these queries I(线段树区间合并)

    SPOJ GSS1_Can you answer these queries I(线段树区间合并) 标签(空格分隔): 线段树区间合并 题目链接 GSS1 - Can you answer these ...

  5. SPOJ 1557. Can you answer these queries II 线段树

    Can you answer these queries II Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 https://www.spoj.com/pr ...

  6. bzoj 2482: [Spoj GSS2] Can you answer these queries II 线段树

    2482: [Spoj1557] Can you answer these queries II Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 145 ...

  7. 【BZOJ2482】[Spoj1557] Can you answer these queries II 线段树

    [BZOJ2482][Spoj1557] Can you answer these queries II Description 给定n个元素的序列. 给出m个询问:求l[i]~r[i]的最大子段和( ...

  8. SPOJ GSS3 Can you answer these queries III[线段树]

    SPOJ - GSS3 Can you answer these queries III Description You are given a sequence A of N (N <= 50 ...

  9. GSS4 2713. Can you answer these queries IV 线段树

    GSS7 Can you answer these queries IV 题目:给出一个数列,原数列和值不超过1e18,有两种操作: 0 x y:修改区间[x,y]所有数开方后向下调整至最近的整数 1 ...

随机推荐

  1. 7.CSMA协议

    载波监听多路访问协议CSMA CS:载波侦听/监听,每一个站在发送数据之前要检测一下总线上是否有其他计算机在发送数据. MA:多点接入,表示许多计算机以多点接入的方式连接在一根总线上 协议思想:发送帧 ...

  2. Oracle忘记用户名和密码以及管理员用户新增修改删除用户

    Oracle忘记密码: 1.以管理员身份登录,打开dos窗口,输入 sqlplus / as sysdba 回车 2.查看当前用户和状态 select username, account_status ...

  3. java不同基本类型之间的运算

    一.不同基本类型在JAVA中,基本类型(除了boolean外)可以自动转换的,转换形式为:byte,short,char – int --long–float–double这就是自动转换的顺序了,其中 ...

  4. ElasticSearch(一)概念介绍及环境搭建

    一.什么是ElasticSearch: Elasticsearch (ES)是一个基于Lucene构建的开源.分布式.RESTful 接口全文搜索引擎.Elasticsearch 还是一个分布式文档数 ...

  5. Java后端总结

    Java后端开发学习路线 编程基础 Java语言 语言基础 基础语法 面向对象 接口 容器 异常 泛型 反射 注解 I/O 图形化(如Swing) JVM 类加载机制 字节码执行机制 jvm内存模型 ...

  6. Maven&mdash;&mdash;软件开发中一个神奇的项目管理工具

    由于本人是从c++转入从事JAVA工作的 所以很多东西要从头学起,相信有很多跟我一样的人吧,那么我们一起来学习. 今天我们一起来认识下Maven这个工具,很多人可能会问题了,为什么说是工具呢?不是写代 ...

  7. Python访问元组

    Python访问元组: 使用索引下标进行访问元组: # 通过索引下标进行访问 tuple_1 = ('a','b','c','d','e','f','g') # 输出元组中的第一个值 print(tu ...

  8. PHP diskfreespace() 函数

    定义和用法 diskfreespace() 函数返回指定目录的可用空间,以字节为单位. 该函数是 disk_free_space() 函数的别名. 语法 diskfreespace(directory ...

  9. 【FZYZOJ】细菌 题解(最短路)

    题目描述 为了研究一种新型细菌(称它为S型细菌)的性质,Q博士将S型细菌放在了一个犹如迷宫一般的通道面前,迷宫中N个站点,每个站点之间以一种单向通道的形式连接,当然,也有可能某两个站点之间是互不联通的 ...

  10. CustomPlot 在Qt下 鼠标点击曲线 显示当前坐标

    此次记录主要是为了下次使用时能回忆起来才做得笔记,若有需改进的地方,请不吝珠玉. widget.cpp #include "widget.h" #include "ui_ ...