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';
}
}
}

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

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

    SPOJ - GSS1:https://vjudge.net/problem/SPOJ-GSS1 参考:http://www.cnblogs.com/shanyr/p/5710152.html?utm ...

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

  3. Spoj 1557 Can you answer these queries II 线段树 随意区间最大子段和 不反复数字

    题目链接:点击打开链接 每一个点都是最大值,把一整个序列和都压缩在一个点里. 1.普通的区间求和就是维护2个值,区间和Sum和延迟标志Lazy 2.Old 是该区间里出现过最大的Sum, Oldlaz ...

  4. 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} ...

  5. Can you answer these queries? HDU - 4027 (线段树,区间开平方,区间求和)

    A lot of battleships of evil are arranged in a line before the battle. Our commander decides to use ...

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

  7. SPOJ GSS1 - Can you answer these queries I(线段树维护GSS)

    Can you answer these queries I SPOJ - GSS1 You are given a sequence A[1], A[2], -, A[N] . ( |A[i]| ≤ ...

  8. SPOJ 1557 GSS2 - Can you answer these queries II (线段树+维护历史最值)

    都说这题是 GSS 系列中最难的,今天做了一下,名副其实 首先你可以想到各种各样的在线乱搞想法,线段树,主席树,平衡树,等等,但发现都不太可行. 注意到题目也没有说强制在线,因此可以想到离线地去解决这 ...

  9. [Codeforces]817F. MEX Queries 离散化+线段树维护

    [Codeforces]817F. MEX Queries You are given a set of integer numbers, initially it is empty. You sho ...

随机推荐

  1. vue自定义过滤器的创建与使用

    原文地址 过滤器:生活中有很多例子,净水器 空气净化器 .过滤器的作用:实现数据的筛选.过滤.格式化. vue1.*版本是有内置的过滤器,但是在vue2.*所有的版本都已经没有自带的过滤器了. 1.过 ...

  2. fdisk中参数配置说明表

    命令 描述 a 设置活动分区标志 b 编辑BSD Unix系统用的磁盘标签 c 设置DOS兼容标志 d 删除分区 l 显示可用的分区类型 m 显示命令选项(帮助) n 添加一个新的分区 o 创建DOS ...

  3. Books Exchange (easy version)   CodeForces - 1249B2

    The only difference between easy and hard versions is constraints. There are nn kids, each of them i ...

  4. AttributeError: module 'unittest' has no attribute 'TestCase'

    一个自己给自己挖的坑 大家千万不要用库的名称命名,特别是刚刚入门的时候.文件夹.文件,都不要用库的名称. 一旦与库重名,就会出现这种 AttributeError. 引以为戒,以后我再这么命名,我就是 ...

  5. SolidWorks学习笔记8 包覆,圆顶

    包覆 在该平面上创建草图,点击A,创建文字 在左侧取消勾选“使用文档字体”,点击字体,重新设置高度,字体. 在草图上点击来放置. 点击特征->包覆, 在模型树中选择有文字的草图 这里面 选择圆柱 ...

  6. python-day6(正式学习)

    流程控制之while循环 语法 循环就是一个重复的过程,人需要重复做某项工作,那么计算机也一样.当ATM验证失败,那么计算机就会让我们再输入一次密码.这时候我们说的循环就是while循环,while循 ...

  7. drf序列化及反序列化

    假如把drf看做一个汉堡包,我们之前讲的模块属于汉堡包前面的盖盖(请求模块.渲染模块)和底底(异常模块.解析模块.响应模块),但是真正中间的夹心没有讲,那么今天我就和大家来看一下汉堡包的夹心(序列化及 ...

  8. Open-falcon监控

    https://book.open-falcon.org/zh_0_2/ 本文档记录了CentOS7.4下open-falcon-v2监控系统的部署流程,以及一些需要注意的地方. 环境准备 安装Red ...

  9. hdu 1969 pie 卡精度的二分

    Pie Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submiss ...

  10. C# 操作地址 从内存中读取写入数据(初级)

    本示例以植物大战僵尸为例, 实现功能为 每1秒让阳光刷新为 9999.本示例使用的游戏版本为 [植物大战僵尸2010年度版], 使用的辅助查看内存地址的工具是  CE. 由于每次启动游戏, 游戏中阳光 ...