线段树
线段树
九条可怜是一个喜欢数据结构的女孩子,在常见的数据结构中,可怜最喜欢的就是线段树。
线段树的核心是懒标记,下面是一个带懒标记的线段树的伪代码,其中 `tag` 数组为懒标记:

其中函数 表示 的左儿子, 表示 的右儿子。
现在可怜手上有一棵 上的线段树,编号为 。这棵线段树上的所有节点的 `tag` 均为 。接下来可怜进行了 次操作,操作有两种:
- ,假设可怜当前手上有 棵线段树,可怜会把每棵线段树复制两份(`tag` 数组也一起复制),原先编号为 的线段树复制得到的两棵编号为 与 ,在复制结束后,可怜手上一共有 棵线段树。接着,可怜会对所有编号为奇数的线段树进行一次 。
- ,可怜定义一棵线段树的权值为它上面有多少个节点 `tag` 为 。可怜想要知道她手上所有线段树的权值和是多少。
Sol
这题很妙。
考虑用概率来表示出现次数。
注意到如果一个点的祖先有标记,那么他也有可能被影响。
可以记a为i这一个节点的1的出现概率,b为i和i的祖先中有一个出现出现1的概率。
这两个互相转移一下。
大致思路是把点分成四类:经过的,覆盖的,pushdown的和覆盖的点的儿子。
最后一类需要区间加。

#include<cstdio> #include<iostream> #include<cstdlib> #include<cstring> #include<algorithm> #include<cmath> #define maxn 100005 #define ll long long #define mod 998244353 using namespace std; int n,m; ll ny=499122177; struct node{ ll a,b,sum,bc,ba; }tr[maxn*8]; void wh(int k){ tr[k].sum=(tr[k*2].sum+tr[k*2+1].sum+tr[k].a)%mod; } void ch1(int k){ tr[k].a=tr[k].a*ny%mod;tr[k].b=tr[k].b*ny%mod;wh(k); } void ch2(int k){ tr[k].a=ny*(tr[k].a+1)%mod;tr[k].b=ny*(tr[k].b+1)%mod;wh(k); } void ch3(int k){ tr[k].a=(tr[k].b+tr[k].a)*ny%mod;tr[k].a%=mod;wh(k); } void ch4(int k){ tr[k].b=ny*(tr[k].b+1)%mod; tr[k].bc=tr[k].bc*ny%mod;tr[k].ba=(tr[k].ba+1)*ny%mod; } void down(int k){ int ls=k*2,rs=k*2+1; if(tr[k].bc!=1){ ll &t=tr[k].bc; tr[ls].b=tr[ls].b*t%mod;tr[ls].bc=tr[ls].bc*t%mod;tr[ls].ba=tr[ls].ba*t%mod; tr[rs].b=tr[rs].b*t%mod;tr[rs].bc=tr[rs].bc*t%mod;tr[rs].ba=tr[rs].ba*t%mod; t=1; } if(tr[k].ba!=0){ ll &t=tr[k].ba; tr[ls].b=(tr[ls].b+t)%mod;tr[ls].ba=(tr[ls].ba+t)%mod; tr[rs].b=(tr[rs].b+t)%mod;tr[rs].ba=(tr[rs].ba+t)%mod; t=0; } } void add(int k,int l,int r,int li,int ri){ if(l>=li&r<=ri){ ch2(k); //if(l<r)ch4(k*2),ch4(k*2+1); tr[k].ba=(tr[k].ba+1)*ny%mod; tr[k].bc=tr[k].bc*ny%mod; return; } down(k); int mid=l+r>>1; if(li<=mid)add(k*2,l,mid,li,ri); else ch3(k*2); if(ri>mid)add(k*2+1,mid+1,r,li,ri); else ch3(k*2+1); ch1(k); } int main(){ cin>>n>>m; ll num=1; for(int i=1;i<maxn;i++)tr[i].bc=1; for(int i=1,op,l,r;i<=m;i++){ scanf("%d",&op); if(op==1){ scanf("%d%d",&l,&r); add(1,1,n,l,r); num=num*2%mod; } else { ll ans=tr[1].sum*num%mod; ans=(ans+mod)%mod; printf("%lld\n",ans); } } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构