题解【SP1043】 GSS1 - Can you answer these queries I
题目描述
You are given a sequence \(A_1, A_2, ..., A_n(|A_i|≤15007,1≤N≤50000)\).
A query is defined as follows:
\(Query(x,y) = Max(a_i+a_{i+1}+...+a_j;x≤i≤j≤y)\).
Given \(M\) queries, your program must output the results of these queries.
输入输出格式
输入格式
- The first line of the input file contains the integer \(N\).
- In the second line, \(N\) numbers follow.
- The third line contains the integer \(M\).
- \(M\) lines follow, where line \(i\) contains \(2\) numbers \(x_i\) and \(y_i\).
输出格式
Your program should output the results of the \(M\) queries, one query per line.
输入输出样例
输入样例#1
3
-1 2 3
1
1 2
输出样例#1
2
题意翻译
给出了序列 \(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\}\)。
给定\(M\)个查询,程序必须输出这些查询的结果,每行一个查询。
题解
\(SPOJ\)的\(GSS\)系列一共有\(8\)题,这\(8\)道题目都是有关数据结构的,与\(Ynoi\)类似。
这是\(SPOJ\)的\(GSS\)系列的第一题,考察的是用线段树求区间最大子段和 (本蒟蒻不会猫树) 。
众所周知,线段树有以下基本的\(3\)个操作:\(pushup\)、\(bulid\)和\(getans\),这\(3\)个操作分别对应合并区间、建树的求答案。
我们尝试用这三种操作解决这道题:
首先,我们定义一个结构体:
struct Node
{
int sum, lans, rans, ans;
} t[50005 << 2];
其中,\(sum\)表示区间和,\(lans\)表示最大前缀和,\(rans\)表示最大后缀和,\(ans\)表示区间内的最大子段和,我们的目标是求出\(x\)~\(y\)区间内的\(ans\)。
然后,我们分析,如何进行\(pushup\)操作。
易知,这个区间内的区间和就是它子区间的和加上它右子区间的和。
区间最大前缀和是它左子区间最大子段和,与左子区间和加上右子区间的最大前缀和的最大值,最大后缀和同理。
考虑如何合并区间最大子段和?
经过分析,我们得出:区间最大子段和就是\(max(\)左子区间的最大子段和,右子区间的最大子段和,
左子区间的最大后缀+右子区间的最大前缀和\()\)。
综上,我们就得出了\(pushup\)的代码:
inline void pushup(int x)
{
t[x].sum = t[x << 1].sum + t[(x << 1) | 1].sum;//求出区间和
t[x].lans = max(t[x << 1].lans, t[x << 1].sum + t[(x << 1) | 1].lans);//区间最大前缀和
t[x].rans = max(t[(x << 1) | 1].rans, t[(x << 1) | 1].sum + t[x << 1].rans);//区间最大后缀和
t[x].ans = max(max(t[x << 1].ans, t[(x << 1) | 1].ans), t[x << 1].rans + t[(x << 1) | 1].lans);//区间最大子段和
}
\(build\)操作与普通线段树的\(build\)操作一模一样。
下面放出\(build\)操作的代码:
void bulid(int s, int o, int p)
{
if (s == o)//已经是叶子节点
{
t[p].sum = t[p].lans = t[p].rans = t[p].ans = gi();//输入并初始化叶子节点的成员
return;
}
int mid = (s + o) >> 1;//找出区间中点
bulid(s, mid, p << 1);//递归左子区间
bulid(mid + 1, o, (p << 1) | 1);//递归右子区间
pushup(p);//合并区间
}
\(getans\)操作同理。
下面放出\(AC\)代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cctype>
using namespace std;
inline int gi()
{
int f = 1, x = 0; char c = getchar();
while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar();}
while (c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar();}
return f * x;
}
int n, m;
struct Node
{
int sum, lans, rans, ans;
} t[50005 << 2];
inline void pushup(int x)//合并操作
{
t[x].sum = t[x << 1].sum + t[(x << 1) | 1].sum;
t[x].lans = max(t[x << 1].lans, t[x << 1].sum + t[(x << 1) | 1].lans);
t[x].rans = max(t[(x << 1) | 1].rans, t[(x << 1) | 1].sum + t[x << 1].rans);
t[x].ans = max(max(t[x << 1].ans, t[(x << 1) | 1].ans), t[x << 1].rans + t[(x << 1) | 1].lans);
}
void bulid(int s, int o, int p)//建树
{
if (s == o)
{
t[p].sum = t[p].lans = t[p].rans = t[p].ans = gi();
return;
}
int mid = (s + o) >> 1;
bulid(s, mid, p << 1);
bulid(mid + 1, o, (p << 1) | 1);
pushup(p);
}
Node getans(int l, int r, int s, int o, int p)//求答案
{
if (l <= s && r >= o)//如果包含区间
{
return t[p];//就直接返回
}
int mid = (s + o) >> 1;//求出中点
if (l > mid) return getans(l, r, mid + 1, o, (p << 1) | 1);//如果左端点在中点右边,就递归右区间
if (r <= mid) return getans(l, r, s, mid, p << 1);//如果右端点在中点左边,就递归左区间
else
{
Node ans, a, b;
a = getans(l, r, s, mid, p << 1), b = getans(l, r, mid + 1, o, (p << 1) | 1);//求出左区间和右区间的各项参数
ans.sum = a.sum + b.sum;
ans.ans = max(max(a.ans, a.rans + b.lans), b.ans);
ans.lans = max(a.lans, a.sum + b.lans);
ans.rans = max(b.rans, b.sum + a.rans);//合并答案
return ans;//最后返回答案
}
}
int main()//进入主函数
{
n = gi();//输入节点个数
bulid(1, n, 1);//建树
m = gi();//输入询问个数
for (int i = 1; i <= m; i++)
{
int x = gi(), y = gi();
printf("%d\n", getans(x, y, 1, n, 1).ans);//求出答案
}
return 0;//结束
}
题解【SP1043】 GSS1 - Can you answer these queries I的更多相关文章
- 线段树 SP1043 GSS1 - Can you answer these queries I
SP1043 GSS1 - Can you answer these queries I 题目描述 给出了序列A[1],A[2],-,A[N]. (a[i]≤15007,1≤N≤50000).查询定义 ...
- [题解] SPOJ GSS1 - Can you answer these queries I
[题解] SPOJ GSS1 - Can you answer these queries I · 题目大意 要求维护一段长度为 \(n\) 的静态序列的区间最大子段和. 有 \(m\) 次询问,每次 ...
- SP1043 GSS1 - Can you answer these queries I 线段树
问题描述 LG-SP1043 题解 GSS 系列第一题. \(q\) 个询问,求 \([x,y]\) 的最大字段和. 线段树,维护 \([x,y]\) 的 \(lmax,rmax,sum,val\) ...
- [SP1043] GSS1 - Can you answer these queries I
传送门:>Here< 题意:求区间最大子段和 $N \leq 50000$ 包括多组询问(不需要支持修改) 解题思路 线段树的一道好题 我们可以考虑,如果一组数据全部都是正数,那么问题等同 ...
- 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} ...
- 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}. 给定M ...
- 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]| ≤ ...
- 线段树【SP1043】GSS1 - Can you answer these queries I
Description 给出了序列\(A_1,A_2,-,A_n\). \(a_i \leq 15007,1 \leq n \leq 50000\).查询定义如下: 查询\((x,y)=max{a_i ...
- 「SP1043」GSS1 - Can you answer these queries I
传送门 Luogu 解题思路 这题就是 GSS3 的一个退化版,不带修改操作的区间最大子段和,没什么好讲的. 细节注意事项 咕咕咕 参考代码 #include <algorithm> #i ...
随机推荐
- 洛谷P3381 MCMF【网络流】
题目描述 如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用. 输入格式 第一行包含四个正整数N.M.S.T,分别表示点的个数.有向 ...
- SpringData JPA快速入门和基本的CRUD操作以及Specifications条件查询
SpringData JPA概述: SpringData JPA 是 Spring 基于 ORM 框架.JPA 规范的基础上封装的一套JPA应用框架,可使开发者用极简的代码即可实现对数据库的访问和操作 ...
- (转)git使用规范
转自:http://www.ruanyifeng.com/blog/2015/08/git-use-process.html 团队开发中,遵循一个合理.清晰的Git使用流程,是非常重要的. 否则,每个 ...
- 2020牛客寒假算法基础集训营5 B.牛牛战队的比赛地 (二分/三分)
https://ac.nowcoder.com/acm/contest/3006/B 三分做法 #include<bits/stdc++.h> #define inf 0x3f3f3f3f ...
- 刷题76. Minimum Window Substring
一.题目说明 题目76. Minimum Window Substring,求字符串S中最小连续字符串,包括字符串T中的所有字符,复杂度要求是O(n).难度是Hard! 二.我的解答 先说我的思路: ...
- Vs2013以管理员身份运行
VS快捷方式目录下的devenv.exe 右键->兼容性疑难解答->疑难解答程序->勾选该程序需要附加权限即可,以后每次打开VS时都会以管理员身份运行了!
- AcWing 1018. 最低通行费
#include<iostream> using namespace std ; ,INF=1e9; int dp[N][N],w[N][N]; int n; int main() { c ...
- 手机app测试要点(复制文)
一.简介 移动应用App已经渗透到每个人的生活.娱乐.学习.工作当中,令人激动.兴奋且具有创造性的各种App犹如雨后春笋般交付到用户手中.各类智能终端也在快速发布,而开发者对于全球移动设备的质量和性能 ...
- 题解【AcWing177】噩梦
题面 考虑双向广搜. 我们需要记录男孩和女孩的当前位置,并且每次都进行扩展. 记录一个数组 \(st[i][j]\) . 如果 \(st[i][j]=0\) ,说明 \((i,j)\) 还没有被男孩和 ...
- [CF1236D] Alice and the Doll - 模拟,STL
[CF1236D] Alice and the Doll Description \(N \times M\)网格,有 \(K\) 个格子里有障碍物.每次经过一个格子的时候只能直走或者右转一次.初态在 ...