题意:有一个 [1,n][1,n][1,n] 的线段树和 mmm 个区间赋值操作,求任取一个操作的子集并按顺序在线段树上跑后线段树上有 lazy 标记的点的个数之和 模 998244353998244353998244353。

n,m≤105n,m\leq 10^5n,m≤105

真·线段树上 dp

考虑线段树的情况很复杂,所以大概率是强行讨论。

显然分结点考虑,即设 f(u)f(u)f(u) 为当前线段树上结点 uuu 有标记的概率。

然后对于一次操作,结点大概分为以下 444 类:

  1. 普通结点:该操作真实操作到的 log⁡\loglog 个结点,这些结点操作后一定有标记。
  2. 文艺结点:普通线段树修改时经过但未覆盖的点。这些点即使有标记访问后也会被下放,所以一定没有标记。
  3. 二逼结点:在父结点只往兄弟结点递归时,可以得到父结点标记的结点。但它是否有标记需要讨论。
  4. 废物结点:和修改没有任何关系的结点。

然后开始讨论

  • 普通结点

f(u)←f(u)+12f(u)\leftarrow \frac{f(u)+1}{2}f(u)←2f(u)+1​

  • 文艺结点

f(u)←f(u)2f(u)\leftarrow \frac {f(u)}2f(u)←2f(u)​

  • 二逼结点

f(u)←f(u)+&#歪比巴卜……2f(u)\leftarrow\frac{f(u)+\texttt{\&\#歪比巴卜……}}{2}f(u)←2f(u)+&#歪比巴卜……​

发现这个修改后有标记的概率不好搞。

然后考场上瞎传参乱搞,然后写崩了……

冷静分析我们实际上需要什么东西。

这个点有标记,当且仅当祖先传下来了一个标记,或者自己本来就有标记。总之就是 1∼u1\sim u1∼u 的路径上至少有一个标记。

这个怎么搞呢?容斥?

实际上直接开个 g(u)g(u)g(u) 记一下就可以了……

重新推一下

  • 普通结点

自己被标记了,所以到根路径上一定也有标记。

f(u)←f(u)+12f(u)\leftarrow \frac{f(u)+1}{2}f(u)←2f(u)+1​

g(u)←g(u)+12g(u)\leftarrow \frac{g(u)+1}{2}g(u)←2g(u)+1​

  • 文艺结点

自己有标记也会被传下去。

f(u)←f(u)2f(u)\leftarrow \frac {f(u)}2f(u)←2f(u)​

g(u)←g(u)2g(u)\leftarrow \frac {g(u)}2g(u)←2g(u)​

  • 二逼结点

本身有标记当且仅当到根路径上有标记。因为祖先的标记都被传下来了,所以路径有标记相当于自己有标记。

f(u)←f(u)+g(u)2f(u)\leftarrow \frac {f(u)+g(u)}2f(u)←2f(u)+g(u)​

g(u)←g(u)+g(u)2=g(u)g(u)\leftarrow \frac {g(u)+g(u)}2=g(u)g(u)←2g(u)+g(u)​=g(u)

  • 废物结点

然后你会发现还有两种小类:

  1. 底层结点

普通结点子树内被减掉的结点,标记不变,但到根路径一定有标记。

g(u)←g(u)+12g(u)\leftarrow \frac {g(u)+1}2g(u)←2g(u)+1​

  1. 路人结点

纯路人,没有任何变化。

然后 普通,文艺,二逼的结点是 O(log⁡n)O(\log n)O(logn) 的,直接暴力。底层结点可以打 lazy 标记,路人结点不管。

复杂度 O(nlog⁡n)O(n\log n)O(nlogn)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
#define MAXN 100005
using namespace std;
inline int read()
{int ans=0;char c=getchar();while (!isdigit(c)) c=getchar();while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();return ans;
}
typedef long long ll;
const int MOD=998244353,INV=(MOD+1)>>1;
int f[MAXN<<3],g[MAXN<<3],s[MAXN<<3];
int add[MAXN<<3],mul[MAXN<<3];
#define lc p<<1
#define rc p<<1|1
inline void update(int p){s[p]=((ll)f[p]+(ll)s[lc]+s[rc])%MOD;}
inline void pushlzy(int p,int m,int v){g[p]=((ll)g[p]*m+v)%MOD;mul[p]=(ll)mul[p]*m%MOD,add[p]=((ll)add[p]*m+v)%MOD;}
inline void pushdown(int p)
{if (add[p]||mul[p]>1){pushlzy(lc,mul[p],add[p]),pushlzy(rc,mul[p],add[p]);add[p]=0,mul[p]=1;}
}
void modify(int p,int l,int r,int ql,int qr)
{if (ql<=l&&r<=qr) return (void)(f[p]=(f[p]+1ll)*INV%MOD,pushlzy(p,INV,INV),update(p));pushdown(p);f[p]=(ll)f[p]*INV%MOD,g[p]=(ll)g[p]*INV%MOD;int mid=(l+r)>>1;if (qr<=mid){f[rc]=((ll)f[rc]+g[rc])*INV%MOD;update(rc);modify(lc,l,mid,ql,qr);return update(p);}if (ql>mid){f[lc]=((ll)f[lc]+g[lc])*INV%MOD;update(lc);modify(rc,mid+1,r,ql,qr); return update(p);}modify(lc,l,mid,ql,qr),modify(rc,mid+1,r,ql,qr);update(p);
}
int main()
{freopen("segment.in","r",stdin);freopen("segment.out","w",stdout);for (int i=0;i<(MAXN<<3);i++) mul[i]=1;int n=read(),cur=1;for (int m=read();m;m--){int t=read();if (t==1){int l,r;l=read(),r=read();modify(1,1,n,l,r);cur=cur*2%MOD;}else printf("%lld\n",(ll)s[1]*cur%MOD);}return 0;
}

【ZJOI2019】线段树【线段树上dp】【大讨论】相关推荐

  1. Educational Codeforces Round 67 (Rated for Div. 2)(D思维题 线段树/E树形dp(换根dp) 二次扫描与换根法)

    心得 D写了个假算法被hack了wtcl- E据涛神说是二次扫描与换根法,看了看好像和树形dp差不多 F概率dp G费用流 回头再补 思路来源 马老师 归神 贤神等代码 http://www.mami ...

  2. UOJ#7. 【NOI2014】购票 | 线段树 凸包优化DP

    题目链接 UOJ #7 题解 首先这一定是DP!可以写出: \[f[i] = \min_{ancestor\ j} \{f[j] + (d[j] - d[i]) * p[i] + q[i]\}\] 其 ...

  3. 洛谷 - P4556 [Vani有约会]雨天的尾巴 /【模板】线段树合并(树上差分+线段树合并)

    题目链接:点击查看 题目大意:给出一棵树,再给出 m 次操作,每次操作会选择两个点 ( x , y ) ,使得这条路径上的所有点的种类 z 加一,最后问每个点的哪个种类出现的频率最高,若多个种类出现频 ...

  4. 17AHU排位赛3 D题 旋转吧!雪月花 ! (DFS序,线段树维护树上最值)

    problem 在一个平面上有n个齿轮,每个齿轮都有自己的初始半径 ri r_i .有n-1对齿轮是互相嵌在一起的,即它们拥有相同的线速度.如果将n个齿轮当作n个点,将n-1条相嵌关系当作n-1条边, ...

  5. YJJ's Salesman HDU - 6447(线段树 单点更新+DP思想)

    YJJ's Salesman 题目链接:HDU - 6447 题意:一个1e9*1e9的地图,要求由(0, 0) -> (1e9, 1e9):只能向下,向右, 向右下移动:地图中有n个点,有宝藏 ...

  6. 雨中的尾巴(线段树合并+树上差分)

    哇这道题 恶心死我 首先要知道,树上差分一般解决的问题是关于树上的覆盖问题 然后遇到覆盖问题尽量不要打树剖(会慢很多) 关于此题 因为这道题覆盖的是 从xxx到yyy的点 所以我们在 x,yx,yx, ...

  7. 2019长沙学院新生赛(A水,B水,C(整除分块),D水,E(巧数学),F(二分+bfs),H(换根dp),I(线段树)J(dp+倍增+lca))

    A-XOR SUM 通过简单观察得知连续四个数的异或值就是等于0,暴力找出左区间和右区间就可以了,最多跑四个单位 0^1^2^3==0   4^5^6^7=0 #include<bits/std ...

  8. HDU3698-Let the light guide us (线段树优化的dp)

    Plain of despair was once an ancient battlefield where those brave spirits had rested in peace for t ...

  9. 线段树 ---- 线段树上区间二分 或者单点二分 codeforces C. Greedy Shopping

    题目大意 题目大意: 给你一个非增的区间现在你有两次操作 1 x y : 把[a1,...ax][a_1,...a_x][a1​,...ax​]里面的数对yyy取maxmaxmax 2 x y : 你 ...

  10. 【BZOJ5461】 【PKUWC2018】—Minimax(线段树合并优化dp)

    传送门 发现其实就是左右2棵子树,左儿子选到某个值的概率就是 选最大值的概率∗右儿子的值比它小的概率选最大值的概率*右儿子的值比它小的概率选最大值的概率∗右儿子的值比它小的概率 +选最小值的概率∗右儿 ...

最新文章

  1. 网站单页面SEO关键词该如何布局更好?
  2. win7系统电脑语言栏怎么更换输入法
  3. WINDOWS2008server安全策略设置
  4. Redis主从复制原理
  5. 如何在论文后面插参考文献
  6. 内网渗透神器CobaltStrike之Beacon详解(三)
  7. e在计算机语言,请问e语言是什么?怎样使用?
  8. springboot 使用 Spring Boot WebSocket 创建聊天室 2-11
  9. Ubuntu Server 18.04 WiFi配置静态ip
  10. Python免杀脚本生成.exe(过火绒过联想没过360)
  11. Chrome浏览器各种崩溃、卡死解决方法
  12. linux操作系统的分类及解释
  13. laravel 微信授权登录
  14. 语音信号处理初学者概念总结
  15. 8种微信小程序赚钱方式
  16. tomcat增加内存
  17. 我来回答,害怕别人赚钱到底是一种什么样的心理
  18. 索尼大变身:消费电子业务转向医疗设备
  19. c盘所有的html文件全删,电脑c盘program files(x86)文件夹可以删除吗
  20. for,while,do...while循环语句的基本知识

热门文章

  1. php支持cs吗,关于composer、phpmd和phpcs于windows中的安装与使用方法
  2. 你和985硕博研究生,差了这些东西
  3. 渣男劈腿,两个女生逼他做出选择,结果......
  4. 听说你趁我不在家,欺负我老婆?
  5. 人体的血管连起来竟能绕地球两圈!?| 今日最佳
  6. 《悦趣式连锁反应》玩转STEM教育!529块积木元件,N+1款炫酷模型
  7. 技术人必备的碎片化时间学习工具
  8. 从串行线程封闭到对象池、线程池
  9. 按照学号查找学生_[源码和文档分享]基于JAVA和MYSQL数据库的学生成绩管理系统...
  10. nashorn js 调用 java_从nashorn(JDK 8 JavaScript引擎)调用char []输入参数调用Java函数?...