Description
给定一棵 ([1,n]) 范围内的广义线段树,(k) 次等概率随机选择一个区间 ([l,r]) 执行区间覆盖操作,问最终 (tag=1) 的节点数量的期望。
(nle 200000,kle 10^9)。
Solution
根据期望的线性性,可以先求出每个节点最终 (tag=1) 的概率,加起来即为答案。
考虑每一个区间覆盖对当前节点 (tag) 的影响,因为祖先节点可能会下传 (tag),因此也要考虑祖先节点的状态。可以将状态分为:
- 当前节点和祖先都没有标记
- 祖先节点有标记,当前节点没有标记
- 当前节点有标记
(3) 种状态。
不妨设父亲节点 (f) 的区间为 ([L,R]),当前节点 (p) 的区间为 ([l,r]),询问区间为 ([ql,qr])。
-
修改与 ([L,R]) 无交,即 (1le qlle qr<L) 或 (R<qlle qrle n):此时对状态无影响。
-
修改包含 (f),并在某个 (u) 的祖先处打标记终止,即 (qlin [1,L],qrin [R,n]),此时会导致祖先节点带上标记。
-
修改包含 (u),在 (u) 上打标记终止,此时 (qlin [1,l],qrin [r,n]) 且不属于上一种情况。此时会导致自己带上标记,并且会让祖先节点的标记全部下传。
-
修改进入了 (f),但下一步只进入 (f) 的另一个儿子而不进入 (u),即 (1le qlle Lle qr< l) ,或 (r<qlle Rle rle n):此时祖先节点的标记会下传。
-
修改与 (u) 相交,进入 (u) 后继续向下递归:此时祖先节点与当前节点的标记都会清零。
分类讨论这 (5) 种情况,设 (f_{i,0/1/2}) 表示考虑了前 (i) 次修改,当前状态为 (0/1/2) 的概率,不难列出转移方程,然后矩阵快速幂优化即可做到 (mathcal O(3^3nlog 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
",ans);
return 0;
}