LOJ 3043: 洛谷 P5280: 「ZJOI2019」线段树
题目传送门:LOJ #3043。
题意简述:
你需要模拟线段树的懒标记过程。
初始时有一棵什么标记都没有的 \(n\) 阶线段树。
每次修改会把当前所有的线段树复制一份,然后对于这些线段树实行一次区间修改操作。
即每次修改后线段树棵数翻倍,第 \(i\) 次修改后,线段树共有 \(2^i\) 棵。
区间修改操作的伪代码如下:

和我日常写的递归式线段树完全一致。
每次询问你这些线段树中有懒标记的节点总数。
修改和询问的总个数为 \(q\),\(1\le n,q\le 10^5\)。
题解:
灵感来源自 Sooke 的题解。
考察一次区间修改操作会影响到的节点,共有 \(5\) 类:
与修改区间相交,但不包含在修改区间内部的节点(浅紫色)。
包含在修改区间内部,但其父亲不存在或不包含在修改区间内部(浅蓝色)。
与修改区间相离,但其父亲与修改区间相交(浅橙色)。
包含在修改区间内部,且其父亲也包含在修改区间内部(深蓝色)。
与修改区间相离,且其父亲也与修改区间相离(深橙色)。

将节点分为这 \(5\) 类并不是没有根据的,可以发现:
若伪代码运行到了第 \(17\) 行,则访问到的是第 \(1\) 类节点。
若伪代码运行到了第 \(14\) 行,则访问到的是第 \(2\) 类节点。
若伪代码运行到了第 \(11\) 行,则访问到的是第 \(3\) 类节点。
而第 \(4,5\) 类节点分别是第 \(2,3\) 类节点的子孙。
根据线段树的复杂度,第 \(1,2,3\) 类节点的个数均为 \(\mathcal{O}(\log n)\),而第 \(4,5\) 类节点的个数为 \(\mathcal{O}(n)\)。
接下来分析每次操作时受到影响的节点:
对于第 \(1\) 类节点,操作后它们必然无懒标记。
对于第 \(2\) 类节点,操作后它们必然有懒标记。
对于第 \(3\) 类节点,操作后它们有无懒标记取决于操作前这个节点到根的链上有无懒标记。
对于第 \(4,5\) 类节点,操作后它们不受影响。
我们考虑维护每次操作后每个节点 \(u\) 有懒标记的树的占比,即在 \(2^i\) 棵树中,节点 \(u\) 有懒标记的树的比值,记作 \(\mathrm{f}[u]\)。
同时,因为第 \(3\) 类节点需要额外信息,维护每次操作后每个节点 \(u\) 到根的路径上有懒标记的树的占比,记作 \(\mathrm{g}[u]\)。
接下来我们考虑一次操作后,每个节点的信息如何更新,注意到同类节点的更新方式是相同的:
对于第 \(1\) 类节点,一半保持原样,另一半无标记,所以 \(\left\langle\mathrm{f}[u],\mathrm{g}[u]\right\rangle=\left\langle\frac{1}{2}\mathrm{f}[u],\frac{1}{2}\mathrm{g}[u]\right\rangle\)。
对于第 \(2\) 类节点,一半保持原样,另一半有标记,所以 \(\left\langle\mathrm{f}[u],\mathrm{g}[u]\right\rangle=\left\langle\frac{1}{2}\mathrm{f}[u]+\frac{1}{2},\frac{1}{2}\mathrm{g}[u]+\frac{1}{2}\right\rangle\)。
对于第 \(3\) 类节点,一半保持原样,另一半的标记取决于 \(u\) 到根的路径,所以 \(\left\langle\mathrm{f}[u],\mathrm{g}[u]\right\rangle=\left\langle\frac{1}{2}(\mathrm{f}[u]+\mathrm{g}[u]),\mathrm{g}[u]\right\rangle\)。
对于第 \(4\) 类节点,一半保持原样,另一半标记不受影响,但到根的路径上一定有标记,所以 \(\left\langle\mathrm{f}[u],\mathrm{g}[u]\right\rangle=\left\langle\mathrm{f}[u],\frac{1}{2}\mathrm{g}[u]+\frac{1}{2}\right\rangle\)。
对于第 \(5\) 类节点,一半保持原样,另一半标记不受影响,到根的路径上的标记也不受影响,所以 \(\left\langle\mathrm{f}[u],\mathrm{g}[u]\right\rangle=\left\langle\mathrm{f}[u],\mathrm{g}[u]\right\rangle\)。
第 \(5\) 类节点的信息没有更改,第 \(4\) 类节点仅有 \(\mathrm{g}\) 有更改,因为第 \(4\) 类节点有 \(\mathcal{O}(n)\) 个,所以必须采用打懒标记的方法来维护。
而对于前 \(3\) 类,直接维护即可。
再多维护一个 \(\mathrm{Sf}[u]\) 表示 \(u\) 的子树中 \(\mathrm{f}[v]\) 值之和即可统计答案。
#include <cstdio>
typedef long long LL;
const int Mod = 998244353;
const int Inv2 = 499122177;
const int MS = 1 << 18;
inline int Add(int x, int y) {
return (x += y) >= Mod ? x - Mod : x;
}
int N, M;
int f[MS], g[MS], Sf[MS], T[MS];
inline void P(int i, int x) {
g[i] = ((LL)g[i] * x + 1 - x + Mod) % Mod;
T[i] = (LL)T[i] * x % Mod;
}
inline void Upd(int i, int Ty) {
if (Ty) Sf[i] = f[i];
else Sf[i] = Add(f[i], Add(Sf[i << 1], Sf[i << 1 | 1]));
}
inline void Psd(int i) {
P(i << 1, T[i]);
P(i << 1 | 1, T[i]);
T[i] = 1;
}
void Build(int i, int l, int r) {
T[i] = 1;
if (l != r) {
Build(i << 1, l, (l + r) >> 1);
Build(i << 1 | 1, ((l + r) >> 1) + 1, r);
}
}
void Mdf(int i, int l, int r, int a, int b) {
if (r < a || b < l) {
f[i] = (LL)(f[i] + g[i]) * Inv2 % Mod;
Upd(i, l == r);
return ;
}
if (a <= l && r <= b) {
f[i] = (LL)(f[i] + 1) * Inv2 % Mod;
Upd(i, l == r);
P(i, Inv2);
return ;
}
Psd(i);
f[i] = (LL)f[i] * Inv2 % Mod;
g[i] = (LL)g[i] * Inv2 % Mod;
Mdf(i << 1, l, (l + r) >> 1, a, b);
Mdf(i << 1 | 1, ((l + r) >> 1) + 1, r, a, b);
Upd(i, 0);
}
int main() {
scanf("%d%d", &N, &M);
Build(1, 1, N);
for (int m = 1, C = 1; m <= M; ++m) {
int op, l, r;
scanf("%d", &op);
if (op == 1) {
scanf("%d%d", &l, &r);
Mdf(1, 1, N, l, r);
C = Add(C, C);
}
else printf("%lld\n", (LL)C * Sf[1] % Mod);
}
return 0;
}
LOJ 3043: 洛谷 P5280: 「ZJOI2019」线段树的更多相关文章
- LOJ 3045: 洛谷 P5326: 「ZJOI2019」开关
题目传送门:LOJ #3045. 题意简述 略. 题解 从高斯消元出发好像需要一些集合幂级数的知识,就不从这个角度思考了. 令 \(\displaystyle \dot p = \sum_{i = 1 ...
- 【LOJ】#3043. 「ZJOI2019」线段树
LOJ#3043. 「ZJOI2019」线段树 计数转期望的一道好题-- 每个点设两个变量\(p,q\)表示这个点有\(p\)的概率有标记,有\(q\)的概率到祖先的路径上有个标记 被覆盖的点$0.5 ...
- 「ZJOI2019」线段树 解题报告
「ZJOI2019」线段树 听说有人喷这个题简单,然后我就跑去做,然后自闭感++,rp++(雾) 理性分析一波,可以发现最后形成的\(2^k\)个线段树,对应的操作的一个子集,按时间顺序作用到这颗线段 ...
- LOJ 2312(洛谷 3733) 「HAOI2017」八纵八横——线段树分治+线性基+bitset
题目:https://loj.ac/problem/2312 https://www.luogu.org/problemnew/show/P3733 原本以为要线段树分治+LCT,查了查发现环上的值直 ...
- LOJ 3089: 洛谷 P5319: 「BJOI2019」奥术神杖
题目传送门:LOJ #3089. 题意简述: 有一个长度为 \(n\) 的母串,其中某些位置已固定,另一些位置可以任意填. 同时给定 \(m\) 个小串,第 \(i\) 个为 \(S_i\),所有位置 ...
- LOJ 3093: 洛谷 P5323: 「BJOI2019」光线
题目传送门:LOJ #3093. 题意简述: 有 \(n\) 面玻璃,第 \(i\) 面的透光率为 \(a\),反射率为 \(b\). 问把这 \(n\) 面玻璃按顺序叠在一起后,\(n\) 层玻璃的 ...
- LOJ 2483: 洛谷 P4655: 「CEOI2017」Building Bridges
题目传送门:LOJ #2483. 题意简述: 有 \(n\) 个数,每个数有高度 \(h_i\) 和价格 \(w_i\) 两个属性. 你可以花费 \(w_i\) 的代价移除第 \(i\) 个数(不能移 ...
- LOJ 2249: 洛谷 P2305: 「NOI2014」购票
题目传送门:LOJ #2249. 题意简述: 有一棵以 \(1\) 号节点为根节点的带边权的树. 除了 \(1\) 号节点的所有节点上都有人需要坐车到达 \(1\) 号节点. 除了 \(1\) 号节点 ...
- @loj - 3043@「ZJOI2019」线段树
目录 @description@ @solution@ @accepted code@ @details@ @description@ 九条可怜是一个喜欢数据结构的女孩子,在常见的数据结构中,可怜最喜 ...
随机推荐
- 自学Zabbix12.3 Zabbix命令-zabbix_agentd
点击返回:自学Zabbix之路 点击返回:自学Zabbix4.0之路 点击返回:自学zabbix集锦 自学Zabbix12.3 Zabbix命令-zabbix_agentd 1. zabbix_age ...
- 【BZOJ4820】[SDOI2017]硬币游戏(高斯消元)
[BZOJ4820][SDOI2017]硬币游戏(高斯消元) 题面 BZOJ 洛谷 题解 第一眼的感觉就是构\(AC\)自动机之后直接高斯消元算概率,这样子似乎就是\(BZOJ1444\)了.然而点数 ...
- 【BZOJ5286】[HNOI2018]转盘(线段树)
[BZOJ5286][HNOI2018]转盘(线段树) 题面 BZOJ 洛谷 题解 很妙的一道题目啊.(全世界除了我这题都有40分,就我是一个状压选手 首先来发现一些性质,我们走一圈一定不会更差. 为 ...
- 神奇的操作——线段树合并(例题: BZOJ2212)
什么是线段树合并? 首先你需要动态开点的线段树.(对每个节点维护左儿子.右儿子.存储的数据,然后要修改某儿子所在的区间中的数据的时候再创建该节点.) 考虑这样一个问题: 你现在有两棵权值线段树(大概是 ...
- 【bzoj3064】 CPU监控
http://www.lydsy.com/JudgeOnline/problem.php?id=3064 (题目链接) 题意 给出一个长度为$n$的数列$A$,同时定义一个辅助数组$B$,$B$开始与 ...
- scrapy-redis爬取豆瓣电影短评,使用词云wordcloud展示
1.数据是使用scrapy-redis爬取的,存放在redis里面,爬取的是最近大热电影<海王> 2.使用了jieba中文分词解析库 3.使用了停用词stopwords,过滤掉一些无意义的 ...
- Mysql服务器处理客户端请求流程
在日常执行mysql语句的过程中,都是客户端进程向服务器进程发送一段文本(MySQL语句),服务器进程处理后再向客户端进程发送一段文本(处理结果). 看似很简单,其实不然,这内容有很多东西是需要注意的 ...
- pacman安装软件包出现损坏
状况 File .pkg.tar.xz is corrupted (invalid or corrupted package (PGP signature)).Do you want to delet ...
- bzoj2989&&4170数列——二进制分组+主席树
题意的转化挺巧妙的 可以联想到曼哈顿距离! 并且,所谓的修改还要查询历史版本,并且修改之间不动只算一次,不就是给平面上加一个点吗? 看成(x,a[x])的点 就是一个菱形区域 转切比雪夫距离,变成矩形 ...
- A1101. Quick Sort
There is a classical process named partition in the famous quick sort algorithm. In this process we ...