recursion有一个整数序列a[n]。现在recursion有m次询问,每次她想知道Max { A[i]+A[i+1]+...+A[j] ; x1 <= i <= y1 , x2 <= j <= y2 , x1 <= x2 , y1 <= y2 }。这么简单的题,recursion当然会做啦,但是为了维持她的傲娇属性,她决定考考你。

Input
输入的第一行为数据组数。对于每组数据,第一行包含一个正整数n和长度为n的序列a[n]。接下来一行有一个正整数m。下面m行分别描述m个询问,每行包含四个整数x1,y1,x2,y2。

Output
对于每组数据输出m行,分别表示m个询问的答案

Sample Input
2
6 3 -2 1 -4 5 2
2
1 1 2 3
1 3 2 5
1 1
1
1 1 1 1
Sample Output
2
3
1

Hint
|A[i]|<=10000,1<=N<=10000,1<=M<=10000

思路:

首先用https://vjudge.net/problem/SPOJ-GSS3 这题的模板可以维护正常的区间询问,单点修改的线段树维护区间最大子段和问题。

然后对于题目的给定两个区间中分别选一个l和r问题,

我们进行分类讨论,我们看答案可能是哪种情况。

首先,如果x2>y1 那么答案就是 ( x1~y1 )中最大后缀数值+ ( y1~x2 ) 区间的数值sum和+ ( x2 + y2 中区间的最大前缀和 )

否则 两个区间就一定有交叉的分布

即 数值的从小到大的顺序是这样: x1,x2,y1 , y2

那么答案可能是以下三种情况:

1、x2~y1 中的最大子段和。

2、l在 x1~x2 之间,y在x2~y2区间

3、l在x1~y1 之间,y在y1~y2 区间,

这三种情况就包含了所有可能。

细节见代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define sz(a) int(a.size())
#define all(a) a.begin(), a.end()
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
ll powmod(ll a, ll b, ll MOD) {ll ans = 1; while (b) {if (b % 2) { ans = ans * a % MOD; } a = a * a % MOD; b /= 2;} return ans;}
inline void getInt(int *p);
const int maxn = 50000 + 7;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
struct node {int l;int r;ll num;ll lm;ll sum;ll rm;
} segment_tree[maxn << 2];
int n;
void pushup(int rt)
{segment_tree[rt].sum = segment_tree[rt << 1].sum + segment_tree[rt << 1 | 1].sum;segment_tree[rt].lm = max(segment_tree[rt << 1].lm, segment_tree[rt << 1].sum + segment_tree[rt << 1 | 1].lm);segment_tree[rt].rm = max(segment_tree[rt << 1 | 1].rm, segment_tree[rt << 1 | 1].sum + segment_tree[rt << 1].rm);segment_tree[rt].num = max(segment_tree[rt << 1].num, segment_tree[rt << 1 | 1].num);segment_tree[rt].num = max(segment_tree[rt].num, segment_tree[rt << 1].rm + segment_tree[rt << 1 | 1].lm);
}void build(int rt, int l, int r)
{segment_tree[rt].l = l;segment_tree[rt].r = r;if (l == r) {scanf("%lld", &segment_tree[rt].num);segment_tree[rt].lm = segment_tree[rt].rm = segment_tree[rt].num;segment_tree[rt].sum = segment_tree[rt].num;return ;}int mid = (l + r) >> 1;build(rt << 1, l, mid);build(rt << 1 | 1, mid + 1, r);pushup(rt);
}node ask(int rt, int l, int r)
{if (l > r) {return node{0, 0, 0, 0, 0, 0};}if (segment_tree[rt].l == l && segment_tree[rt].r == r) {return segment_tree[rt];}int mid = (segment_tree[rt].r + segment_tree[rt].l) >> 1;if (l > mid) {return ask(rt << 1 | 1, l, r);} else if (r <= mid) {return ask(rt << 1, l, r);} else {node res1 = ask(rt << 1, l, mid);node res2 = ask(rt << 1 | 1, mid + 1, r);node res;res.sum = res1.sum + res2.sum;res.lm = max(res1.lm, res1.sum + res2.lm);res.rm = max(res2.rm, res2.sum + res1.rm);res.num = max(res1.num, res2.num);res.num = max(res.num, res1.rm + res2.lm);return res;}
}
void update(int rt, int x, int val)
{if (segment_tree[rt].l == x && segment_tree[rt].r == x) {segment_tree[rt].num = val;segment_tree[rt].lm = val;segment_tree[rt].rm = val;segment_tree[rt].sum = val;return ;}int mid = (segment_tree[rt].l + segment_tree[rt].r) >> 1;if (x <= mid) {update(rt << 1, x, val);} else {update(rt << 1 | 1, x, val);}pushup(rt);
}
ll solve(int x1, int y1, int x2, int y2)
{if (y1 < x2) {ll res = ask(1, x1, y1).rm;res += ask(1, y1 + 1, x2 - 1).sum;res += ask(1, x2, y2).lm;return res;} else {ll res = ask(1, x2, y1).num;res = max(res, ask(1, x1, x2).rm + ask(1, x2, y2).lm - ask(1, x2, x2).sum);res = max(res, ask(1, x1, y1).rm + ask(1, y1, y2).lm - ask(1, y1, y1).sum);return res;}
}
int main()
{//freopen("D:\\code\\text\\input.txt","r",stdin);//freopen("D:\\code\\text\\output.txt","w",stdout);int t;scanf("%d", &t);while (t--) {scanf("%d", &n);build(1, 1, n);int m;scanf("%d", &m);while (m--) {int x1, x2, y1, y2;scanf("%d %d %d %d", &x1, &y1, &x2, &y2);printf("%lld\n", solve(x1, y1, x2, y2));}}return 0;
}inline void getInt(int *p)
{char ch;do {ch = getchar();} while (ch == ' ' || ch == '\n');if (ch == '-') {*p = -(getchar() - '0');while ((ch = getchar()) >= '0' && ch <= '9') {*p = *p * 10 - ch + '0';}} else {*p = ch - '0';while ((ch = getchar()) >= '0' && ch <= '9') {*p = *p * 10 + ch - '0';}}
}

转载于:https://www.cnblogs.com/qieqiemin/p/11447506.html

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

  1. Can you answer these queries I SPOJ - GSS1 (线段树维护区间连续最大值/最大连续子段和)...

    You are given a sequence A[1], A[2], ..., A[N] . ( |A[i]| ≤ 15007 , 1 ≤ N ≤ 50000 ). A query is defi ...

  2. SP1043 GSS1 - Can you answer these queries I(线段树,区间最大子段和(静态))

    题目描述 给出了序列A[1],A[2],-,A[N]. (a[i]≤15007,1≤N≤50000).查询定义如下: 查询(x,y)=max{a[i]+a[i+1]+...+a[j]:x≤i≤j≤y} ...

  3. 【线段树】GSS5 - Can you answer these queries V(luogu-SPOJ 2916)

    正题 luogu-SPOJ 2916 题目大意 给你一个序列,有若干询问,每次给出左右端点的区间,问你最大字段和 解题思路 用线段树维护区间信息,询问的区间如果有交则分类讨论求解 code #incl ...

  4. SPOJ 375 Query on a tree(线段树维护树链剖分)

    题目链接:http://www.spoj.com/problems/QTREE/ 题意:给出一个树,两种操作:(1)修改某条边的权值:(2)询问某两个顶点之间边的最大值. 思路:树的路径剖分和线段树维 ...

  5. 【uoj#164】[清华集训2015]V 线段树维护历史最值

    题目描述 给你一个长度为 $n$ 的序列,支持五种操作: $1\ l\ r\ x$ :将 $[l,r]$ 内的数加上 $x$ : $2\ l\ r\ x$ :将 $[l,r]$ 内的数减去 $x$ , ...

  6. spoj 2916. Can you answer these queries V(线段树)

    题目链接:http://www.spoj.com/problems/GSS5/ 题意:给出n个数,求区间最大子段和,但是限制了子段的起点终点,起点要在[x1,y1]内,终点要在[x2,y2]内. 思路 ...

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

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

    前言 最近沉迷于数据结构,感觉数据结构很有意思. 正文 分析 先来分类讨论一下 1. x2<y1x2<y1x2<y1 如果 y1<x2y1<x2y1<x2 的话,答 ...

  9. Can you answer these queries III (线段树维护最大子段和)

    题意: 求一个区间的最大连续和. 0:表示把A[x]改成y 1:表示求[x,y]这个区间的最大连续和. 题解: 线段树维护四个变量. 倒着讲,先来看如何维护这四个变量. summax代表这个区间连续最 ...

最新文章

  1. Kdevelop的简单使用和调试_JunJun~的博客-CSDN博客_kdevelop使用教程
  2. jQuery学习笔记6:表单选择器
  3. 字符串补充知识及列表类型
  4. 几种常用的图像处理函数库
  5. Hover伪类在IE6中的实现
  6. PHP框架的ORM思想:O类的实例化 R数据表 M映射XML
  7. HDU 1506 Largest Rectangle in a Histogram(dp、单调栈)
  8. Spring Security MVC登录注销示例教程
  9. 大学大专mysql考试试卷_MySQL数据库基础应用-中国大学mooc-试题题目及答案
  10. 用Typescript如火如荼地进行angular.js
  11. Cisco基础(六):配置目前网络环境、项目阶段练习
  12. 会声会影编辑面板常用功能介绍
  13. SDK学院--易接网游SDK中间件接入使用说明-Unity3D游戏接口
  14. 删除回收站右键找回清空的文件
  15. Pytest测试用例之setup与teardown方法(一)
  16. UrlRewritingNet 完美实现 ASP.NET 2.0 中的URL重写(映射)
  17. 洛谷 P3389 【模板】高斯消元法 × 洛谷 P2455 [SDOI2006]线性方程组
  18. #资讯 #生活 #科技 李斌称蔚来手机进展顺利,微信iOS版内测更新,威马CEO沈晖回应12亿年薪,迅雷网游加速器停运,这就是今天的其它大新闻
  19. 中山起湾周边学校有计算机吗,【趣味数据】乐有家:入学对口小区一直变?中山东区入学住哪里比较好...
  20. redmine2.0 + mongrel

热门文章

  1. jMeter工具里左边树形结构里一些节点属性的介绍
  2. 一段TCP socket和WebSocket互相交互的调试代码
  3. echo和pwd获取文件路径的区别对比
  4. java 安卓界面 可视化_Monkey可视化工具开发(android篇)
  5. mysql主主 主键冲突_mysql主从复制原理,主主复制时主键冲突解决
  6. python数据统计代码_Python 数据的累加与统计的示例代码
  7. java轻功游戏,会轻功又可以飞的游戏(3d大型游戏)
  8. python多核运行程序怎么关闭_在多核上运行程序
  9. mac全选文字的快捷键_最全Mac系统快捷键一览
  10. matlab转向语句,MATLAB控制语句