题目链接

题目

题目描述

小H给你一个数组 \(a\) ,要求支持以下两种操作:

  1. 0 l r \((1 \leq l \leq r \leq n)\),询问区间 \([l,r]\) 中权值和最大的有效子区间的权值和,一个子区间被认为是有效的当且仅当这个子区间中没有两个相邻的偶数或者奇数。

  2. 1 x v \((1 \leq x \leq n,-10^9 \leq v \leq 10^9)\) ,将 \(a[x]\) 的值修改为 \(v\) 。

输入描述

第一行读入两个正整数 \(n,m(1 \leq n,m \leq 10^5)\) 第二行读入 \(n\) 个整数,第 \(i\) 个表示 \(a[i](-10^9 \leq a[i] \leq 10^9)\) 接下来 \(m\) 行,每行三个数表示操作,描述见题目描述。

输出描述

输出每个询问的答案。

示例1

输入

10 10
-9 -8 -8 -8 2 -7 -5 2 2 3
0 3 5
0 4 4
0 2 4
1 6 6
1 1 6
1 5 9
0 1 2
1 5 -8
0 2 4
1 3 -2

输出

2
-8
-8
6
-8

题解

知识点:线段树。

见到这种连续段最大值的,先维护三个信息,区间有效最大值 \(mx\) 、区间左端点开始的有效最大值 \(lmx\) 、区间右端点开始的有效最大值 \(rmx\) ,用以维护合并。

继续考虑,合并需要端点的奇偶性相反才可行,因此需要维护左端点奇偶性 \(lodd\) 、右端点奇偶性 \(rodd\) 。

同时,考虑到 \(lmx,rmx\) 合并时会出现跨越两段的情况,需要再维护一个区间权值和 \(sum\) 。当左右可跨越时,可以用 \(lmx\) 与左子区间 \(sum\) 加 右子区间 \(lmx\) 取最大值, \(rmx\) 同理。需要注意, \(sum\) 不能用 \(lmx,rmx\) 替代,因为权值是有正有负的, \(sum\) 不一定是 \(lmx,rmx\) ,必须多维护一个 \(sum\) 。

对于 \(sum\) ,我们还需要来判断整个区间是否为有效区间,从而判断 \(sum\) 是否可用。为了少设一个变量保存区间是否整个有效(当然设了也行,写起来容易点),我们设 \(sum\) 初值为极小值 \(-10^{18}\) 的表示无效值,更新时取 \(sum\) 与左右子区间的 \(sum\) 的和的最大值即可。显然,左右子区间存在一个无效值,则区间的值一定无效。

因此,区间信息要维护 \(mx,lmx,rmx,lodd,rodd,sum\) 。

合并时, \(lodd,rodd\) 直接继承即可,接下来分两步:

  1. \(mx\) 取左右子区间 \(mx\) 的最大值, \(lmx,rmx\) 直接继承。

  2. 若左子区间 \(rodd\) 和右子区间 \(lodd\) 不同,则在第一步的基础上考虑跨越两段的情况。

    \(mx\) 需要再与左子区间 \(rmx\) 加右子区间 \(lmx\) 的和取最大值。

    \(lmx,rmx\) 考虑特殊情况,已经在考虑维护信息的时候分析过了。

    \(sum\) 也分析过了。

修改时,直接修改即可,过程非常朴素,就不讲了。

另外,由于线段树结构的问题,我需要多加一个表示区间是否存在的 \(exist\) 以用来合并无效区间时特判,这个完全可以用先判断后递归避免,但是我懒23333。

时间复杂度 \(O((n+m) \log n)\)

空间复杂度 \(O(n)\)

代码

#include <bits/stdc++.h>
using namespace std;
using ll = long long; struct T {
bool exist = 0; // 区间是否存在
ll mx = -1e18; // 有效区间最大值
ll sum = -1e18; // 区间权值和(区间权值和不能用 lmx,rmx 替代)
bool lodd = 0, rodd = 0; // 左/右端点的奇偶性
ll lmx = -1e18, rmx = -1e18; // 从左/右端点出发的最大值
friend T operator+(const T &a, const T &b) {
if (!a.exist) return b;
if (!b.exist) return a;
T x = T();
x.exist = 1;
x.mx = max(a.mx, b.mx);
x.lodd = a.lodd, x.rodd = b.rodd;
x.lmx = a.lmx, x.rmx = b.rmx;
if (a.rodd ^ b.lodd) {
x.mx = max(x.mx, a.rmx + b.lmx);
x.sum = max(x.sum, a.sum + b.sum); // 取最大值,防止溢出
x.lmx = max(x.lmx, a.sum + b.lmx);
x.rmx = max(x.rmx, a.rmx + b.sum);
}
return x;
}
};
struct F {
ll upd;
T operator()(const T &x) {
return{
1,
upd,
upd,
(bool)(upd % 2),(bool)(upd % 2),
upd,upd,
};
}
}; template<class T, class F>
class SegmentTree {
int n;
vector<T> node; void update(int rt, int l, int r, int x, F f) {
if (r < x || x < l) return;
if (l == r) return node[rt] = f(node[rt]), void();
int mid = l + r >> 1;
update(rt << 1, l, mid, x, f);
update(rt << 1 | 1, mid + 1, r, x, f);
node[rt] = node[rt << 1] + node[rt << 1 | 1];
} T query(int rt, int l, int r, int x, int y) {
if (r < x || y < l) return T();
if (x <= l && r <= y) return node[rt];
int mid = l + r >> 1;
return query(rt << 1, l, mid, x, y) + query(rt << 1 | 1, mid + 1, r, x, y);
} public:
SegmentTree(const vector<T> &src) { init(src); } void init(const vector<T> &src) {
assert(src.size() >= 2);
n = src.size() - 1;
node.assign(n << 2, T());
function<void(int, int, int)> build = [&](int rt, int l, int r) {
if (l == r) return node[rt] = src[l], void();
int mid = l + r >> 1;
build(rt << 1, l, mid);
build(rt << 1 | 1, mid + 1, r);
node[rt] = node[rt << 1] + node[rt << 1 | 1];
};
build(1, 1, n);
} void update(int x, F f) { update(1, 1, n, x, f); } T query(int x, int y) { return query(1, 1, n, x, y); }
}; int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n, m;
cin >> n >> m;
vector<T> a(n + 1);
for (int i = 1;i <= n;i++) {
int x;
cin >> x;
a[i] = {
1,
x,
x,
(bool)(x % 2),(bool)(x % 2),
x,x,
};
}
SegmentTree<T, F> sgt(a);
while (m--) {
int op;
cin >> op;
if (op == 0) {
int l, r;
cin >> l >> r;
cout << sgt.query(l, r).mx << '\n';
}
else {
int x, v;
cin >> x >> v;
sgt.update(x, { v });
}
}
return 0;
}

NC15162 小H的询问的更多相关文章

  1. Wannafly挑战赛10 D 小H的询问(线段树)

    题目链接  Problem D 这个题类似 SPOJ GSS3 做过那个题之后其实就可以秒掉这题了. 考虑当前线段树维护的结点 在那道题的基础上,这个题要多维护几个东西,大概就是左端点的奇偶性,右端点 ...

  2. BZOJ 3781: 小B的询问

    3781: 小B的询问 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 643  Solved: 435[Submit][Status][Discuss ...

  3. hihocoder 1347 小h的树上的朋友

    传送门 时间限制:18000ms单点时限:2000ms内存限制:512MB 描述 小h拥有$n$位朋友.每位朋友拥有一个数值$V_i$代表他与小h的亲密度.亲密度有可能发生变化.岁月流逝,小h的朋友们 ...

  4. Bzoj 3781: 小B的询问 莫队,分块,暴力

    3781: 小B的询问 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 426  Solved: 284[Submit][Status][Discuss ...

  5. 2018.07.01 洛谷小B的询问(莫队)

    P2709 小B的询问 题目描述 小B有一个序列,包含N个1~K之间的整数.他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数 ...

  6. 小H和密码

    链接:https://www.nowcoder.com/acm/contest/72/B来源:牛客网 题目描述     小H在击败怪兽后,被一个密码锁挡住了去路     密码锁由N个转盘组成,编号为1 ...

  7. AC日记——小B的询问 洛谷 P2709

    小B的询问 思路: 水题: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 50005 #define ll ...

  8. BZOJ_3781_小B的询问_莫队

    BZOJ_3781_小B的询问_莫队 Description 小B有一个序列,包含N个1~K之间的整数.他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值 ...

  9. hihocoder-1347 小h的树上的朋友(lca+线段树)

    题目链接: 小h的树上的朋友 时间限制:18000ms 单点时限:2000ms 内存限制:512MB 描述 小h拥有n位朋友.每位朋友拥有一个数值Vi代表他与小h的亲密度.亲密度有可能发生变化. 岁月 ...

  10. 洛谷——P2709 小B的询问

    P2709 小B的询问 莫队算法,弄两个指针乱搞即可 这应该是基础莫队了吧 $x^2$可以拆成$((x-1)+1)^2$,也就是$(x-1)^2+1^2+2\times (x-1)$,那么如果一个数字 ...

随机推荐

  1. 43 干货系列从零用Rust编写负载均衡及代理,内网穿透方案完整部署

    wmproxy wmproxy已用Rust实现http/https代理, socks5代理, 反向代理, 静态文件服务器,四层TCP/UDP转发,七层负载均衡,内网穿透,后续将实现websocket代 ...

  2. Ubuntu安装jdk的步骤

    .markdown-body { line-height: 1.75; font-weight: 400; font-size: 16px; overflow-x: hidden; color: rg ...

  3. SV 数据类型-2

    动态数组 数组定义的时候不用给定数组元素个数 动态数组实例 例1 队列

  4. P1914 小书童——凯撒密码

    1.题目介绍 小书童--凯撒密码 题目背景 某蒟蒻迷上了 "小书童",有一天登陆时忘记密码了(他没绑定邮箱 or 手机),于是便把问题抛给了神犇你. 题目描述 蒟蒻虽然忘记密码,但 ...

  5. CSS 动画 : 创建 3D 立方体

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. 频率 音调 对应表 FFT频谱分析原理

    Frequency in hertz (semitones above or below middle C) Octave→Note↓ 0 1 2 3 4 5 6 7 8 9 C 16.352 (−4 ...

  7. Java21 + SpringBoot3整合Redis,使用Lettuce连接池,推荐连接池参数配置,封装Redis操作

    目录 前言 相关技术简介 Redis 实现步骤 引入maven依赖 修改配置文件 定义Redis配置类 定义Redis服务类,封装Redis常用操作 使用Redis服务类 总结 前言 近日心血来潮想做 ...

  8. [转帖]总结:shell中的if条件判断

    一.if 的基本语法 if [ command ];then xxx elif [ command ];then xxx else xxx fi 二.常见的一些写法案例 1.if [ "x$ ...

  9. [转帖]《Linux性能优化实战》笔记(22)—— 网络丢包问题分析

    所谓丢包,是指在网络数据的收发过程中,由于种种原因,数据包还没传输到应用程序中,就被丢弃了.这些被丢弃包的数量,除以总的传输包数,也就是我们常说的丢包率.丢包率是网络性能中最核心的指标之一.丢包通常会 ...

  10. [转帖]淫技巧 | 如何查看已连接的wifi密码

    https://blog.csdn.net/DynmicResource/article/details/120134984?spm=1001.2014.3001.5502 主题使用方法:https: ...