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@ 九条可怜是一个喜欢数据结构的女孩子,在常见的数据结构中,可怜最喜 ...
随机推荐
- MT【55】近零点
[Among the natural enemy of mathematics, the most important thing is that how do we konw somethi ...
- Mysql 主从服务器数据同步
安装2台windows Server 服务器,分别安装Mysql,配置环境变量,完成安装确认在CMD窗口可以使用Mysql命令 在Master服务器上创建同步账号,确保Slave服务器能访问Maste ...
- 【BZOJ4503】两个串(FFT)
[BZOJ4503]两个串(FFT) 题面 给定串\(S\),以及带通配符的串\(T\),询问\(T\)在\(S\)中出现了几次.并且输出对应的位置. \(|S|,|T|<=10^5\),字符集 ...
- c++11 条件变量 生产者-消费者 并发线程
http://baptiste-wicht.com/posts/2012/04/c11-concurrency-tutorial-advanced-locking-and-condition-vari ...
- eclipse index 不工作 F3 不能找到头文件
To add paths containing code to parse, follow these steps :1. Right click on the project2. Select Pr ...
- SpringMvc的Url映射和传参案例
Springmvc的基本使用,包括url映射.参数映射.页面跳转.ajax和文件上传 以前学习的时候写的代码案例,今天整理笔记的时候找到了,很久没有来园子了,发上来当个在线笔记用吧,免的时间长了又忘了 ...
- Redis我想入门——数据类型
每一个数据库都有自己的数据类型.同样子redis为我们提供了五种类型的数据——字符串.哈希.列表.集合.有序集合.我们知道关系型数据的数据存放型式是一张二维表.用行和列来表示数据之间的关系.redis ...
- A1069. The Black Hole of Numbers
For any 4-digit integer except the ones with all the digits being the same, if we sort the digits in ...
- 编译Uboot——错误记录
我使用的是ZLG的EasyARM i.MX280A的开发板.官方提供的编译器时arm-fsl-linux-gnueabihf(gcc 4.4.4).自己尝试使用arm-linaro-linux-gnu ...
- P2422 良好的感觉
P2422 良好的感觉 给定一段序列, 其中元素 \(0 \leq a_{i} \leq 100000\) 定义一段子段 \([L, R]\) 的舒适值为 \(\min_{L \leq i \leq ...