[灵魂拷问♂]系列

[灵魂拷问♂]系列

SP1043 GSS1 - Can you answer these queries I

  • 题目:链接
  • 大致题意:求区间最大子段和,不带修改。
  • 题解:
  • 对于每个线段树节点。维护以下几个值:

    l, r:左右端点

    sum:区间和

    val:区间最大子段和

    lv:一定包括区间左端点的最大子段和

    rv:一定包括区间右端点的最大子段和

  • lv转移:lv = max(左儿子的lv, 左儿子的sum + 右儿子的lv)
  • rv转移:rv = max(右儿子的rv,右儿子的sum + 左儿子的rv)
  • val转移:val = max(max(左儿子的val, 右儿子的val), 左儿子rv + 右儿子lv)
  • 这几种转移很好理解,就是分类讨论。
  • 线段树的分类讨论无非就是都在mid左边的,都在mid右边的,横跨mid的。
  • 注意,查询的时候。我们不能写成以下版本。
if(l <= mid) res = max(res, ask(p << 1, l, r));
if(r > mid) res = max(res, ask(p << 1 | 1, l, r));
return res;
  • 因为这样写表达的含义就是指答案只来自于左区间和右区间。例如区间和、区间覆盖。但是当答案有来自于(取出左右区间的信息然后进行操作后得到的新信息)时,就要分三类讨论转移。
  • 所以这题的查询代码如下
T ask(int p, int l, int r) //注意这里的函数返回值是一个结构体,方便操作
{
    if(t[p].l >= l && t[p].r <= r) return t[p];
    int mid = t[p].l + t[p].r >> 1;
    if(mid < l) return ask(p2, l, r); //答案都来自右儿子
    else if(mid >= r) return ask(p1, l, r); //答案都来自左儿子
    else //答案来自左儿子或右儿子或(左右儿子信息融合后的信息)
    {
        T t1 = ask(p1, l, r), t2 = ask(p2, l, r), now;
        now.sum = t1.sum + t2.sum;
        now.lv = max(t1.lv, t1.sum + t2.lv);
        now.rv = max(t2.rv, t2.sum + t1.rv);
        now.l = l, now.r = r;
        now.val = max(max(t1.val, t2.val), t1.rv + t2.lv);
        return now;
    }
}
  • 代码:
#include <iostream>
#include <cstdio>
#define N 50005
#define p1 (p << 1)
#define p2 (p << 1 | 1)
using namespace std;

struct T {int l, r, val, lv, rv, sum;} t[N * 4];
int n, m;

int read()
{
    int x = 0, f = 1; 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 x *= f;
}

void up(int p)
{
    t[p].sum = t[p1].sum + t[p2].sum;
    t[p].lv = max(t[p1].lv, t[p1].sum + t[p2].lv);
    t[p].rv = max(t[p2].rv, t[p2].sum + t[p1].rv);
    t[p].val = max(t[p1].rv + t[p2].lv, max(t[p1].val, t[p2].val));
}

void build(int p, int l, int r)
{
    t[p].l = l, t[p].r = r;
    if(l == r)
    {
        int v = read();
        t[p].lv = t[p].rv = v;
        t[p].val = t[p].sum = v;
        return;
    }
    int mid = l + r >> 1;
    build(p1, l, mid), build(p2, mid + 1, r);
    up(p);
}

T ask(int p, int l, int r)
{
    if(t[p].l >= l && t[p].r <= r) return t[p];
    int mid = t[p].l + t[p].r >> 1;
    if(mid < l) return ask(p2, l, r);
    else if(mid >= r) return ask(p1, l, r);
    else
    {
        T t1 = ask(p1, l, r), t2 = ask(p2, l, r), now;
        now.sum = t1.sum + t2.sum;
        now.lv = max(t1.lv, t1.sum + t2.lv);
        now.rv = max(t2.rv, t2.sum + t1.rv);
        now.l = l, now.r = r;
        now.val = max(max(t1.val, t2.val), t1.rv + t2.lv);
        return now;
    }
}

int main()
{
    cin >> n;
    build(1, 1, n);
    cin >> m;
    for(int i = 1; i <= m; i++)
    {
        int l = read(), r = read();
        printf("%d\n", ask(1, l, r).val);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/BigYellowDog/p/11792938.html

时间: 2024-08-24 20:11:00

[灵魂拷问♂]系列的相关文章

灵魂拷问:如何检查Java数组中是否包含某个值 ?

摘自:https://www.cnblogs.com/qing-gee/p/12053156.html 在逛 programcreek 的时候,我发现了一些专注细节但价值连城的主题.比如说:如何检查Java数组中是否包含某个值 ?像这类灵魂拷问的主题,非常值得深入地研究一下. 另外,我想要告诉大家的是,作为程序员,我们千万不要轻视这些基础的知识点.因为基础的知识点是各种上层技术共同的基础,只有彻底地掌握了这些基础知识点,才能更好地理解程序的运行原理,做出更优化的产品. 我曾在某个技术论坛上分享过

灵魂拷问:Java如何获取数组和字符串的长度?length还是length()?

限时 1 秒钟给出答案,来来来,听我口令:"Java 如何获取数组和字符串的长度?length 还是 length()?" 在逛 programcreek 的时候,我发现了上面这个主题.说实话,我当时脑海中浮现出了这样一副惊心动魄的画面: 面试官老马坐在我的对面,地中海式的发型令我敬佩有加.尽管略显疲惫,但他仍然自信地向我抛出了上面这个问题.稍稍迟疑了一下,我回答说:"数组用 length,字符串用 length 跟上小括号".老马不愧是面试中的高手,一瞬间就从我的

工厂设计模式灵魂拷问-Java实现

show me the code and take to me,做的出来更要说的明白 GitHub项目JavaHouse同步收录 喜欢就点个赞呗! 你的支持是我分享的动力! 引入 我们经常听到工厂模式,比如说 Spring 用了工厂模式啦,面试也会被问到工厂模式等等,这见工厂模式是日常开发中比较重要的一种设计模式.其实工厂模式也是比较简单的一种设计模式,这年头似乎不了解工厂模式,你都不好意思说你学过 编程一样(手动狗头).那么,允许我灵魂拷问一下,你真的了解工厂模式吗. UML类图 不急,我们先

还在被大妈灵魂拷问?使用Python轻松完成垃圾分类!

目录0 环境1 引言2 思路 3 图像分类 4 总结 0 环境 Python版本:3.6.8 系统版本:macOS Mojave Python Jupyter Notebook 1 引言 七月了,大家最近一定被一项新的政策给折磨的焦头烂额,那就是垃圾分类.<上海市生活垃圾管理条例>已经正式实施了,相信还是有很多的小伙伴和我一样,还没有完全搞清楚哪些应该扔在哪个类别里.感觉每天都在学习一遍垃圾分类,真令人头大. 听说一杯没有喝完的珍珠奶茶应该这么扔1.首先,没喝完的奶茶水要倒在水池里2.珍珠,水

面试灵魂拷问之JS,请问你头皮发麻没有?

JS数据类型之问-概念篇 1.JS原始数据类型有哪些?引用数据类型有哪些?在 JS 中,存在着 7 种原始值,分别是: boolean null undefined number string symbol bigint引用数据类型:对象Object(包含普通对象-Object,数组对象-Array,正则对象-RegExp,日期对象-Date,数学函数-Math)函数Function2.说出下面运行的结果,解释原因. function test(person) { person.age = 26

【灵魂拷问】你真的懂得Mysql的管理和使用吗?

作者 | Jeskson 来源 | 达达前端小酒馆 MySQL管理,数据库管理和数据表管理,用户管理. 初始化数据库,创建数据库,查看数据库,删除数据库. 创建数据表,查看数据表,修改数据表,删除数据表. 用户管理,创建与删除用户,授予与回收用户权限,设置与更改用户密码. 数据库管理 初始化数据库 mysqld --initialize 启动数据库: 使用windows服务器管理界面启动:或使用MySQL命令启动. mysql -u root -p 创建数据库 CREATE DATABASE语句

灵魂拷问第9篇:HTTPS为什么让数据传输更安全?

谈到HTTPS, 就不得不谈到与之相对的HTTP.HTTP的特性是明文传输,因此在传输的每一个环节,数据都有可能被第三方窃取或者篡改,具体来说,HTTP 数据经过 TCP 层,然后经过WIFI路由器.运营商和目标服务器,这些环节中都可能被中间人拿到数据并进行篡改,也就是我们常说的中间人攻击. 为了防范这样一类攻击,我们不得已要引入新的加密方案,即 HTTPS. HTTPS并不是一个新的协议, 而是一个加强版的HTTP.其原理是在HTTP和TCP之间建立了一个中间层,当HTTP和TCP通信时并不是

灵魂拷问第1篇:能不能说一说浏览器缓存?

缓存是性能优化中非常重要的一环,浏览器的缓存机制对开发也是非常重要的知识点.接下来以三个部分来把浏览器的缓存机制说清楚: 强缓存 协商缓存 缓存位置 强缓存 浏览器中的缓存作用分为两种情况,一种是需要发送HTTP请求,一种是不需要发送. 首先是检查强缓存,这个阶段不需要发送HTTP请求. 如何来检查呢?通过相应的字段来进行,但是说起这个字段就有点门道了. 在HTTP/1.0和HTTP/1.1当中,这个字段是不一样的.在早期,也就是HTTP/1.0时期,使用的是Expires,而HTTP/1.1使

灵魂拷问第2篇:能不能说一说浏览器的本地存储?各自优劣如何?

浏览器的本地存储主要分为Cookie.WebStorage和IndexedDB, 其中WebStorage又可以分为localStorage和sessionStorage.接下来我们就来一一分析这些本地存储方案. Cookie Cookie 最开始被设计出来其实并不是来做本地存储的,而是为了弥补HTTP在状态管理上的不足. HTTP 协议是一个无状态协议,客户端向服务器发请求,服务器返回响应,故事就这样结束了,但是下次发请求如何让服务端知道客户端是谁呢? 这种背景下,就产生了 Cookie. C