NC15162 小H的询问
题目
题目描述
小H给你一个数组 \(a\) ,要求支持以下两种操作:
0 l r \((1 \leq l \leq r \leq n)\),询问区间 \([l,r]\) 中权值和最大的有效子区间的权值和,一个子区间被认为是有效的当且仅当这个子区间中没有两个相邻的偶数或者奇数。
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\) 直接继承即可,接下来分两步:
\(mx\) 取左右子区间 \(mx\) 的最大值, \(lmx,rmx\) 直接继承。
若左子区间 \(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的询问的更多相关文章
- Wannafly挑战赛10 D 小H的询问(线段树)
题目链接 Problem D 这个题类似 SPOJ GSS3 做过那个题之后其实就可以秒掉这题了. 考虑当前线段树维护的结点 在那道题的基础上,这个题要多维护几个东西,大概就是左端点的奇偶性,右端点 ...
- BZOJ 3781: 小B的询问
3781: 小B的询问 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 643 Solved: 435[Submit][Status][Discuss ...
- hihocoder 1347 小h的树上的朋友
传送门 时间限制:18000ms单点时限:2000ms内存限制:512MB 描述 小h拥有$n$位朋友.每位朋友拥有一个数值$V_i$代表他与小h的亲密度.亲密度有可能发生变化.岁月流逝,小h的朋友们 ...
- Bzoj 3781: 小B的询问 莫队,分块,暴力
3781: 小B的询问 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 426 Solved: 284[Submit][Status][Discuss ...
- 2018.07.01 洛谷小B的询问(莫队)
P2709 小B的询问 题目描述 小B有一个序列,包含N个1~K之间的整数.他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数 ...
- 小H和密码
链接:https://www.nowcoder.com/acm/contest/72/B来源:牛客网 题目描述 小H在击败怪兽后,被一个密码锁挡住了去路 密码锁由N个转盘组成,编号为1 ...
- AC日记——小B的询问 洛谷 P2709
小B的询问 思路: 水题: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 50005 #define ll ...
- BZOJ_3781_小B的询问_莫队
BZOJ_3781_小B的询问_莫队 Description 小B有一个序列,包含N个1~K之间的整数.他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值 ...
- hihocoder-1347 小h的树上的朋友(lca+线段树)
题目链接: 小h的树上的朋友 时间限制:18000ms 单点时限:2000ms 内存限制:512MB 描述 小h拥有n位朋友.每位朋友拥有一个数值Vi代表他与小h的亲密度.亲密度有可能发生变化. 岁月 ...
- 洛谷——P2709 小B的询问
P2709 小B的询问 莫队算法,弄两个指针乱搞即可 这应该是基础莫队了吧 $x^2$可以拆成$((x-1)+1)^2$,也就是$(x-1)^2+1^2+2\times (x-1)$,那么如果一个数字 ...
随机推荐
- 运筹学 | 退化的最优解 vs 无穷多最优解?
退化的最优解: 单纯形表的基可行解中,出现等于零的基变量.或者,按最小比值来确定出基向量时,存在两个以上相同最小比值. 出现的原因:模型中存在多余的约束. 无穷多最优解: 单纯形表中,按最大检验数 σ ...
- asp.net core之实时应用
本文将介绍ASP.NET Core SignalR,这是一个强大的实时通信库,用于构建实时.双向通信应用程序.我们将探讨SignalR的基本概念.架构和工作原理,并提供一些示例代码来帮助读者更好地理解 ...
- 07-verilog & sytem verilog
一.数据类型 二值逻辑变量 bit 不赋值的时候,变量初始默认为0 x或z的值会转变为0 bit vector--bit矢量 bit [msb,lsb] variable_name = [initia ...
- 问题--VSCODE终端中文乱码问题
1.问题 问题如下,终端出现中文乱码问题 根本原因是VSCODE是UFT-8编码,而终端显示的中文则是GBK编码 网上很多都是改VSCODE为GBK编码,但改终端为UFT-8也挺方便 2.解决方法 1 ...
- Laravel - Eloquent 更新数据
public function ormUpdate() { # 1.通过模型更新数据 /* $student = Student::find(14); ...
- electron打包,使用electron-packager
构建项目可以使用electron-forge构建,但是这个东西打包比较坑,mac运行报错,win下会有缓存机制,也就是热更新无效 所以选择使用electron-packager打包 sudo npm ...
- SpringMVC08——拦截器——2021-05-11
拦截器概述 SpringMVC的拦截器(Interceptor)类似于Servlet中的过滤器(Filter),它主要用于拦截用户请求并做相应的处理. 例如:进行权限验证.记录请求信息的日志.判断用户 ...
- blackbox的简单学习-监控web服务是否正常以及证书过期时间
blackbox的简单学习-监控web服务是否正常以及证书过期时间 下载blackbox https://github.com/prometheus/blackbox_exporter 可以在rele ...
- [转帖]前后台切换命令(ctrl+z jobs bg fg &)
当我在终端里面运行某个命令的时候,结果不是很快就能出来的那种,或者是一大堆字在屏幕上狂翻.这个时候,有时ctrl+c也不起作用,那我会用ctrl+z退出来,这个很有效,但是说实话我不知道为什么这个可以 ...
- [转帖]DBWR与LGWR的写入机制
https://www.jianshu.com/p/6c87cb6cd320 读与写是每个数据库提供的最基本的功能.当数据库中出现第一个进程时,总免不了要将数据从磁盘上加载到内存中,一次数据库的物理I ...