Description
给定一棵 \([1,n]\) 范围内的广义线段树,\(k\) 次等概率随机选择一个区间 \([l,r]\) 执行区间覆盖操作,问最终 \(tag=1\) 的节点数量的期望。
\(n\le 200000,k\le 10^9\)。
Solution
根据期望的线性性,可以先求出每个节点最终 \(tag=1\) 的概率,加起来即为答案。
考虑每一个区间覆盖对当前节点 \(tag\) 的影响,因为祖先节点可能会下传 \(tag\),因此也要考虑祖先节点的状态。可以将状态分为:
- 当前节点和祖先都没有标记
- 祖先节点有标记,当前节点没有标记
- 当前节点有标记
\(3\) 种状态。
不妨设父亲节点 \(f\) 的区间为 \([L,R]\),当前节点 \(p\) 的区间为 \([l,r]\),询问区间为 \([ql,qr]\)。
-
修改与 \([L,R]\) 无交,即 \(1\le ql\le qr<L\) 或 \(R<ql\le qr\le n\):此时对状态无影响。
-
修改包含 \(f\),并在某个 \(u\) 的祖先处打标记终止,即 \(ql\in [1,L],qr\in [R,n]\),此时会导致祖先节点带上标记。
-
修改包含 \(u\),在 \(u\) 上打标记终止,此时 \(ql\in [1,l],qr\in [r,n]\) 且不属于上一种情况。此时会导致自己带上标记,并且会让祖先节点的标记全部下传。
-
修改进入了 \(f\),但下一步只进入 \(f\) 的另一个儿子而不进入 \(u\),即 \(1\le ql\le L\le qr< l\) ,或 \(r<ql\le R\le r\le n\):此时祖先节点的标记会下传。
-
修改与 \(u\) 相交,进入 \(u\) 后继续向下递归:此时祖先节点与当前节点的标记都会清零。
分类讨论这 \(5\) 种情况,设 \(f_{i,0/1/2}\) 表示考虑了前 \(i\) 次修改,当前状态为 \(0/1/2\) 的概率,不难列出转移方程,然后矩阵快速幂优化即可做到 \(\mathcal O(3^3n\log k)\).
Code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=4e5+10,mod=998244353;
int n,k,m[N],tot,L[N],R[N],fa[N],p[N],q[N],g[N],r[N];
inline void dfs(int l,int r,int f){
int p=++tot;L[p]=l;R[p]=r;fa[p]=f;
if(L[p]!=R[p]){
scanf("%d",&m[p]);
dfs(l,m[p],p);dfs(m[p]+1,r,p);
}
}
inline int add(int x,int y){return (x+y>=mod)?x+y-mod:x+y;}
inline int dec(int x,int y){return (x-y<0)?x-y+mod:x-y;}
inline int ksm(int x,int y){
int ret=1;
for(;y;y>>=1,x=1ll*x*x%mod) if(y&1) ret=1ll*ret*x%mod;
return ret;
}
struct matrix{
int c[3][3];
inline void init(int d){
for(int i=0;i<3;++i) for(int j=0;j<3;++j) c[i][j]=i==j?d:0;
}
inline matrix operator *(const matrix &A){
matrix ret;
for(int i=0;i<3;++i){
for(int j=0;j<3;++j){
ll tmp=0;
for(int k=0;k<3;++k) tmp+=1ll*c[i][k]*A.c[k][j];
ret.c[i][j]=tmp%mod;
}
}
return ret;
}
inline matrix operator ^(int k){
matrix ret,A=*this;ret.init(1);
for(;k;k>>=1,A=A*A) if(k&1) ret=ret*A;
return ret;
}
};
inline int S(int x){return (1ll*x*(x+1)/2)%mod;}
int main(){
scanf("%d%d",&n,&k);
dfs(1,n,0);
int al=S(n),all=ksm(S(n),mod-2),ans=0;
for(int i=1;i<=tot;++i){
int l=L[i],r=R[i],fl=L[fa[i]],fr=R[fa[i]];
int p1=add(S(fl-1),S(n-fr));//与父亲无交
int p2=1ll*fl*(n-fr+1)%mod;//标记祖先
int p3=dec(1ll*l*(n-r+1)%mod,p2);//标记自己
int p4=add(dec(S(l-1),S(fl-1)),dec(S(n-r),S(n-fr)));//下传父亲,不进入自己
int p5=dec(al,add(add(p1,p2),add(p3,p4)));//与自己交但不包含
matrix A;A.init(0);
A.c[0][0]=1ll*add(p1,add(p4,p5))*all%mod;A.c[0][1]=1ll*p5*all%mod;A.c[0][2]=1ll*p5*all%mod;
A.c[1][0]=1ll*p2*all%mod;A.c[1][1]=1ll*add(p1,p2)*all%mod;
A.c[2][0]=1ll*p3*all%mod;A.c[2][1]=1ll*add(p3,p4)*all%mod;A.c[2][2]=1ll*dec(al,p5)*all%mod;
A=A^k;
ans=add(ans,A.c[2][0]);
}
printf("%d\n",ans);
return 0;
}