[题解] SPOJ GSS1 - Can you answer these queries I
[题解] SPOJ GSS1 - Can you answer these queries I
· 题目大意
要求维护一段长度为 \(n\) 的静态序列的区间最大子段和。
有 \(m\) 次询问,每次询问输出区间 \([L,R]\) 的最大子段和。
\(|a[i]| \leq 15007\),\(1 \leq m,n\leq5\times10^4\)
· 解题思路
首先想到如果用线段树的方法,那么预处理时间复杂度为\(O(n)\),总询问复杂度为\(O(m\cdot logn)\)。
当然这么想在这一题中没问题,但是如\(m\)的范围更大一点呢?比如\(1 \leq m \leq 1 \times10^7\)。这时候如果用线段树,很有可能会\(TLE\)。
既然没有修改,那么可以用\(ST\)表或者猫树这种 \(O(1)\) 查询的数据结构来完成这一题,于是笔者选择用猫树来完成这一题。
因为ST表太丑了(doge)
总时间复杂度为\(O(n\cdot logn+m)\)
· 代码实现
注释在代码里
#include <cstdio>
#include <algorithm>
#include <ctype.h>
#define reg register
using namespace std;
namespace io {
template<typename T>inline void read(T &x) {
char f=0,ch; x = 0;
while(!isdigit(ch=getchar())) f |= ch == '-';
while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
x = f? -x: x;
}
char ch[20];
template<typename T>inline void write(T x) {
(x < 0) && (x = -x, putchar('-'));
x || putchar('0');
reg int i=0;
while(x) ch[i++] = x % 10 ^ 48, x /= 10;
while(i) putchar(ch[--i]);
}
}//快读快写
#define rd io::read
#define wt io::write
const int maxN = 100020;
struct CatTree {
int pre, sum;
}t[maxN << 1][22];//维护一下区间前缀/后缀最大值,用于合并,然后维护一下区间子串最大值
int d[maxN << 1], pos[maxN << 1], a[maxN << 1];
int len=2, n, m;
void init(int, int, int);
int query(int, int);
int main() {
freopen("1.in", "r", stdin);
freopen("1.out", "w", stdout);
rd(n);
while(len < n) len <<= 1;
for(reg int i = 1; i <= n; ++i) rd(a[i]);
for(reg int i = 1; i <= len << 1; ++i) d[i] = d[i >> 1] + 1;
init(1, 1, len);
rd(m);
for(reg int i = 1, l, r; i <= m; ++i) {
rd(l); rd(r);
printf("%d\n", query(l, r));
}
return 0;
}
void init(int k, int l, int r) {
if (l==r) {pos[l]=k;return;}
int mid = l + r >> 1, pre , str;
pre = str = t[mid][d[k]].sum = t[mid][d[k]].pre = a[mid];
str = max(str, 0);
for(reg int i = mid - 1; i >= l; --i) {
pre += a[i], str += a[i];
t[i][d[k]].sum = max(t[i + 1][d[k]].sum, str);
t[i][d[k]].pre = max(t[i + 1][d[k]].pre, pre);str = max(str, 0);
}//处理左边区间子串最大值和左边区间后缀最大值。
pre = str = t[mid + 1][d[k]].sum = t[mid + 1][d[k]].pre = a[mid + 1];
str = max(str, 0);
for(reg int i = mid + 2; i <= r; ++i) {
pre += a[i], str += a[i];
t[i][d[k]].sum = max(t[i - 1][d[k]].sum, str);
t[i][d[k]].pre = max(t[i - 1][d[k]].pre, pre);str = max(str, 0);
}
init(k << 1, l, mid);init(k << 1 | 1, mid + 1, r);
}
int query(int l, int r) {
if (l == r) return a[l];
int fa = d[pos[l]] - d[pos[l] ^ pos[r]];//找到x和y的LCA
return max(max(t[l][fa].sum, t[r][fa].sum), t[l][fa].pre + t[r][fa].pre);
}
//最后答案就等于Max{左边的区间子串最大值,右边的区间子串最大值,左边的后缀最大值+右边的前缀最大值}
[题解] SPOJ GSS1 - Can you answer these queries I的更多相关文章
- 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]| ≤ ...
- SPOJ GSS1 Can you answer these queries I[线段树]
Description You are given a sequence A[1], A[2], ..., A[N] . ( |A[i]| ≤ 15007 , 1 ≤ N ≤ 50000 ). A q ...
- SPOJ GSS1 Can you answer these queries I
Time Limit: 115MS Memory Limit: 1572864KB 64bit IO Format: %lld & %llu Description You are g ...
- SPOJ GSS1 Can you answer these queries I ——线段树
[题目分析] 线段树裸题. 注意update的操作,写结构体里好方便. 嗯,没了. [代码] #include <cstdio> #include <cstring> #inc ...
- 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 ...
- GSS7 spoj 6779. Can you answer these queries VII 树链剖分+线段树
GSS7Can you answer these queries VII 给出一棵树,树的节点有权值,有两种操作: 1.询问节点x,y的路径上最大子段和,可以为空 2.把节点x,y的路径上所有节点的权 ...
- 线段树 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).查询定义 ...
- GSS3 SPOJ 1716. Can you answer these queries III gss1的变形
gss2调了一下午,至今还在wa... 我的做法是:对于询问按右区间排序,利用splay记录最右的位置.对于重复出现的,在splay中删掉之前出现的位置所在的节点,然后在splay中插入新的节点.对于 ...
- 题解【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 f ...
随机推荐
- Unittest方法 -- 测试固件(TestFixture)
前置和后置 1.setUp:在写测试用例的时候,每次操作其实都是基于打开浏览器输入对应网址这些操作,这个就是执行用例的前置条件.2.tearDown:执行完用例后,为了不影响下一次用例的执行,一般有个 ...
- 每天五分钟Go - 常量
常量的声明 常量使用const进行对不会被改变值的修饰符 const 常量名 [常量类型] = 常量值,和变量的声名一样可以省略类型 const a=1 const b="a" c ...
- javascript学习(五)之标准对象
一.RegExp:正则表达式是一种用来匹配字符串的强有力的武器.它的设计思想是用一种描述性的语言来给字符串定义一个规则, 凡是符合规则的字符串,我们就认为它"匹配"了,否则,该字符 ...
- jvm源码解读--13 gc_root中的栈中oop的mark 和copy 过程分析
粘贴源码 package com.test; import java.util.Random; public class Test { static int number=12; private in ...
- vsCode开发flutter项目
Visual Studio Code 安装: 下载链接:https://code.visualstudio.com/ 下载完成后根据步骤自行安装. 使用vsCode开发flutter项目需要部 ...
- 论文笔记:(2019)LDGCNN : Linked Dynamic Graph CNN-Learning on PointCloud via Linking Hierarchical Features
目录 摘要 一.引言 A.基于视图的方法 B.基于体素的方法 C.基于几何的方法 二.材料 三.方法 A.问题陈述 B.图生成 C.图特征提取 D.变换不变函数 E.LDGCNN架构 F.冻结特征提取 ...
- Java on Visual Studio Code的更新 – 2021年7月
Nick zhu, Senior Program Manager, Developer Division at Microsoft 大家好,欢迎来到 7 月版的 Visual Studio Code ...
- 全网最硬核Handler面试题深度解析
1.简述Handler的实现原理 Android 应用是通过消息驱动运行的,在 Android 中一切皆消息,包括触摸事件,视图的绘制.显示和刷新等等都是消息.Handler 是消息机制的上层接口,平 ...
- 【Android面试揭秘】面试官说“回去等通知”,我到底会不会等来通知?
前言 大部分情况下,面试结束后,面试官都会跟你说:我们会在1-2个工作日内通知你面试结果. 许多人认为:所谓「等通知」其实是面试官委婉地给你「发拒信」.但是,这不是「等通知」的全部真相. 这篇文章,我 ...
- vue 源码详解(二): 组件生命周期初始化、事件系统初始化
vue 源码详解(二): 组件生命周期初始化.事件系统初始化 上一篇文章 生成 Vue 实例前的准备工作 讲解了实例化前的准备工作, 接下来我们继续看, 我们调用 new Vue() 的时候, 其内部 ...