[题解] 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的更多相关文章

  1. 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]| ≤ ...

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

  3. SPOJ GSS1 Can you answer these queries I

    Time Limit: 115MS   Memory Limit: 1572864KB   64bit IO Format: %lld & %llu Description You are g ...

  4. SPOJ GSS1 Can you answer these queries I ——线段树

    [题目分析] 线段树裸题. 注意update的操作,写结构体里好方便. 嗯,没了. [代码] #include <cstdio> #include <cstring> #inc ...

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

  6. GSS7 spoj 6779. Can you answer these queries VII 树链剖分+线段树

    GSS7Can you answer these queries VII 给出一棵树,树的节点有权值,有两种操作: 1.询问节点x,y的路径上最大子段和,可以为空 2.把节点x,y的路径上所有节点的权 ...

  7. 线段树 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).查询定义 ...

  8. GSS3 SPOJ 1716. Can you answer these queries III gss1的变形

    gss2调了一下午,至今还在wa... 我的做法是:对于询问按右区间排序,利用splay记录最右的位置.对于重复出现的,在splay中删掉之前出现的位置所在的节点,然后在splay中插入新的节点.对于 ...

  9. 题解【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 ...

随机推荐

  1. Mybatis order by 动态传参出现的一个小bug

    大家好,我是老三,一个平平无奇的CRUD仔. 今天,我正在愉快地CRUD,突然发现出现一个Bug,我们来看看是怎么回事吧! 问题由来 一个简单的需求,要求把和当前用户相关的数据置顶展示. 这里,我用了 ...

  2. Laravel 6 – 搭建管理后台的用户认证“脚手架”工具

    1. 下载Laravel/ui 命令: composer require laravel/ui "^1.0" -dev 注意laravel framework 6只支持版本1的la ...

  3. Python - 基础数据类型 list 列表

    什么是列表 列表是一个有序的序列 列表中所有的元素放在 [ ] 中间,并用逗号分开 一个 列表 可以包含不同类型的元素,但通常使用时各个元素类型相同 特征 占用空间小,浪费内存空间少 声明列表变量 列 ...

  4. MYSQL一个设备上的主从复制实现-windows

    只记录一次在一个设备上实现mysql主从复制的过程,很详细,建议收藏,用到的时候照着步骤做就可以,会记录所有需要注意到的细节和一些容易遇到的坑以及解决办法! 如果需要在同一台电脑(服务器)上实现mys ...

  5. Linkerd 金丝雀部署与 A/B 测试

    本指南向您展示如何使用 Linkerd 和 Flagger 来自动化金丝雀部署与 A/B 测试. 前提条件 Flagger 需要 Kubernetes 集群 v1.16 或更新版本和 Linkerd ...

  6. CSRF+XSRF+SSRF简单介绍

    CSRF 使用DVWA靶机,选择low级别,然后更改密码 伪造网页连接 http://localhost:8083/DVWA-master/vulnerabilities/csrf/?password ...

  7. QML用Instantiator动态创建顶级窗口

    关键点 使用Model驱动Instantiator QML里面的hashmap: QQmlPropertyMap 上一次说到用 QQmlApplicationEngine 多次load的方式创建多个一 ...

  8. Mybatis学习笔记-动态SQL

    概念 根据不同环境生成不同SQL语句,摆脱SQL语句拼接的烦恼[doge] 本质:SQL语句的拼接 环境搭建 搭建数据库 CREATE TABLE `blog`( `id` VARCHAR(50) N ...

  9. Vue2中父子组件通信的几种常用方法

    源码地址 点击查看演示源码 Vue2父子传参:props 首先在父组件中引入子组件,然后以属性的方式将数据传递给子组件 父组件: <template> <div class=&quo ...

  10. Hello World!!

    已经工作了一年多,现在才开始写博客.话说,种一棵树最好的时机是十年前,其次是现在,我觉得不迟.俗话说滴水穿石,我想把一些东西,都慢慢积累起来,看见自己的成长.既方便查看,更不容易忘记.可能在网上已经有 ...