「ZJOI2019」线段树
传送门
Description
线段树的核心是懒标记,下面是一个带懒标记的线段树的伪代码,其中 tag 数组为懒标记:
其中函数\(Lson(Node)\)表示\(Node\)的左儿子,\(Rson(Node)\)表示\(Node\)的右儿子。
有一棵 \([1,n]\)上的线段树,编号为\(1\) 。初始时什么标记都没有。
每次修改会把当前所有的线段树复制一份,然后对于这些线段树实行一次区间修改操作。
每次修改后线段树棵数翻倍,第 \(i\)次修改后,线段树共有 \(2^i\) 棵。
每次询问这些线段树中有标记的点的总数。
询问个数\(q\),\(1\leq n,q \leq 10^5\)
Solution
一道很有特色的题目
考察的是对线段树区间修改的认知
\(f_x\)表示\(x\)号节点有标记的线段树占的比例
\(g_x\)表示\(x\)号节点到根路径上有标记的线段树占的比例
首先,把每次区间修改的点分成\(5\)类
- 在找到目标节点前经过的节点,它们的标记全部下传,所以\(f_x=\frac{1}{2}f_x,g_x=\frac{1}{2}g_x\)
- 目标节点,完全被覆盖,递归过程中被全部被打上标记,\(f_x=\frac{1}{2}+\frac{1}{2}f_x,g_x=\frac{1}{2}+\frac{1}{2}g_x\)
- \(2\)类节点的子树内的其它节点,递归过程中不变,\(f_x=f_x,g_x=\frac{1}{2}+\frac{1}{2}g_x\)
- 在\(pushdown\)中被访问到的节点,但完全不被覆盖,\(f_x=\frac{1}{2}f_x+\frac{1}{2}g_x,g_x=g_x\)
- \(4\)类节点的子树内的其它节点,递归过程不变,\(f_x=f_x,g_x=g_x\)
同时,我们去要维护子树内的\(f_x\)的和
对于\(g_x\)的修改,我们采用打懒标记的方式,当找到\(2\)类节点时,直接对它打上\(*\frac{1}{2}\)的标记
Code
#include<bits/stdc++.h>
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define ll long long
#define reg register
inline int read()
{
reg int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
const int MN=1e5+5,mod=998244353,Inv2=499122177;
int N,M;
int f[MN<<3],g[MN<<3],sf[MN<<3],lz[MN<<3];
#define Add(x,y) (((x)+(y))%mod)
#define Mul(x,y) (1ll*(x)*(y)%mod)
#define ls (x<<1)
#define rs (x<<1|1)
void C(int x,int val){lz[x]=Mul(lz[x],val);g[x]=Add(Mul(g[x],val),1-val+mod);}
void down(int x){if(lz[x]^1)C(ls,lz[x]),C(rs,lz[x]),lz[x]=1;}
void up(int x){sf[x]=Add(f[x],Add(sf[ls],sf[rs]));}
void Build(int x,int l,int r)
{
lz[x]=1;if(l==r) return;
reg int mid=(l+r)>>1;
Build(ls,l,mid);Build(rs,mid+1,r);
}
void Modi(int x,int l,int r,int a,int b)
{
if(r<a||l>b)
{
f[x]=Mul(Inv2,Add(f[x],g[x]));
up(x);return;
}
if(l>=a&&r<=b)
{
f[x]=Add(Inv2,Mul(Inv2,f[x]));
C(x,Inv2);up(x);return;
}
down(x);f[x]=Mul(Inv2,f[x]);g[x]=Mul(Inv2,g[x]);
reg int mid=(l+r)>>1;
Modi(ls,l,mid,a,b);
Modi(rs,mid+1,r,a,b);
up(x);
}
int main()
{
N=read();M=read();Build(1,1,N);
reg int opt,l,r,Num=1;
while(M--)
{
opt=read();
if(opt==2) printf("%d\n",Mul(sf[1],Num));
else l=read(),r=read(),Modi(1,1,N,l,r),Num=Mul(2ll,Num);
}
return 0;
}
Blog来自PaperCloud,未经允许,请勿转载,TKS!
「ZJOI2019」线段树的更多相关文章
- 【LOJ】#3043. 「ZJOI2019」线段树
LOJ#3043. 「ZJOI2019」线段树 计数转期望的一道好题-- 每个点设两个变量\(p,q\)表示这个点有\(p\)的概率有标记,有\(q\)的概率到祖先的路径上有个标记 被覆盖的点$0.5 ...
- 「ZJOI2019」线段树 解题报告
「ZJOI2019」线段树 听说有人喷这个题简单,然后我就跑去做,然后自闭感++,rp++(雾) 理性分析一波,可以发现最后形成的\(2^k\)个线段树,对应的操作的一个子集,按时间顺序作用到这颗线段 ...
- LOJ 3043: 洛谷 P5280: 「ZJOI2019」线段树
题目传送门:LOJ #3043. 题意简述: 你需要模拟线段树的懒标记过程. 初始时有一棵什么标记都没有的 \(n\) 阶线段树. 每次修改会把当前所有的线段树复制一份,然后对于这些线段树实行一次区间 ...
- 【LOJ3043】「ZJOI2019」线段树
题面 问题可以转化为每次区间覆盖操作有 \(\frac{1}{2}\) 的概率进行,求标记和的期望.于是我们只要求出所有点有标记的概率即可. 我们设 \(f_i\) 表示节点 \(i\) 有标记的概率 ...
- @loj - 3043@「ZJOI2019」线段树
目录 @description@ @solution@ @accepted code@ @details@ @description@ 九条可怜是一个喜欢数据结构的女孩子,在常见的数据结构中,可怜最喜 ...
- 「模板」 线段树——区间乘 && 区间加 && 区间求和
「模板」 线段树--区间乘 && 区间加 && 区间求和 原来的代码太恶心了,重贴一遍. #include <cstdio> int n,m; long l ...
- Loj #2570. 「ZJOI2017」线段树
Loj #2570. 「ZJOI2017」线段树 题目描述 线段树是九条可怜很喜欢的一个数据结构,它拥有着简单的结构.优秀的复杂度与强大的功能,因此可怜曾经花了很长时间研究线段树的一些性质. 最近可怜 ...
- @loj - 2093@ 「ZJOI2016」线段树
目录 @description@ @solution@ @accepted code@ @details@ @description@ 小 Yuuka 遇到了一个题目:有一个序列 a1,a2,..., ...
- 「ZJOI2019」&「十二省联考 2019」题解索引
「ZJOI2019」&「十二省联考 2019」题解索引 「ZJOI2019」 「ZJOI2019」线段树 「ZJOI2019」Minimax 搜索 「十二省联考 2019」 「十二省联考 20 ...
随机推荐
- idea全局护眼色绿豆沙
1.settings->plugins->BackgroundImage 2.在导航栏选择Help->FindAction 3.set background image 4.选择图片 ...
- SQL 基本概念、通用语法与分类
一.SQL 概念 1.什么是 SQL Structured Query Language 结构化查询语句 2.SQL 作用 (1)是一种所有关系型数据库的查询规范,不同的数据库都支持. (2)通用 ...
- UCOSIII信号量
信号量通常分为两种 二进制信号量 计数型信号量 二进制信号量 二进制信号量只能取0和1两个值 计数型信号量 计数型信号量的范围由OS_SEM_CTR决定.OS_SEM_CTR可以为8位,16位和32位 ...
- Python学习日记(十四) 正则表达式和re模块
正则表达式: 它是字符串的一种匹配模式,用来处理字符串,可以极大地减轻处理一些复杂字符串的代码量 字符组:它是在同一位置可能出现的各种字符组成了一个字符组,用[]表示,但是它的结果只能是一个数字或者一 ...
- MySQL之Prepared Statements
1.概述 prepared statement在MySQL4.1中引进并且增加了一些新的命令: COM_STMT_PREPARE COM_STMT_EXECUTE COM_STMT_CLOSE COM ...
- 【转】高性能网络编程3----TCP消息的接收
这篇文章将试图说明应用程序如何接收网络上发送过来的TCP消息流,由于篇幅所限,暂时忽略ACK报文的回复和接收窗口的滑动. 为了快速掌握本文所要表达的思想,我们可以带着以下问题阅读: 1.应用程序调用r ...
- unity 之 背包系统
此方法只是用于学习和实验所以细节不必要求 一.Ui设置. 画布配置如下: 布局: 说明: 画布里面首先建立一个panel命名为weapon1,在其内部再建立4个panel用于装备的卡槽,装备以imag ...
- MongoDB与Python的交互
驱动模块 pymongo是python里常用的操作MongoDB的驱动模块 可用pip下载安装 pip install pymongo 创建连接 MongoClient是MongoDB的客户端代理对象 ...
- 苹果cms和海洋cms通用的百度主动推送工具
百度主动推送的代码,不需要每天手动去添加地址推送,只要浏览器打开推送请求,不要关掉浏览器,程序自动帮你推送.(该插件只推送内容页,支持动态.伪静态.静态页面的推送,但这三种地址规则需要去代码里面自行拼 ...
- 行为型模式(八) 职责链模式(Chain of Responsibility)
一.动机(Motivate) 在软件构建过程中,一个请求可能被多个对象处理,但是每个请求在运行时只能有一个接受者,如果显示指定,将必不可少地带来请求发送者与接受者的紧耦合.如何使请求的发送者不需要指定 ...
