P6655 题解
直接计数其实不好记,不如计数转期望。
令 \(f_i\) 表示点 \(i\) 成为制高点概率,不难发现期望就是 \(\sum f_i\)。
根据定义对于 \(f\) 我们有如下转移 \(f_i = \frac{\sum_{j=l_i}^{r_i} f_j}{r_i-l_i+1}\) 又因为 \(l_i \leq r_i < i\) 所以按照 \(i\) 的顺序转移即可保证正确性,那么用主席树维护转移即可。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn = 2e5+114;
const int top = 100000000000;
const int mod = 998244353;
int n;
struct Node{
int ls,rs,sum;
}tr[maxn*60];
#define ls(cur)(tr[cur].ls)
#define rs(cur)(tr[cur].rs)
int rt[maxn];
int tot;
void insert(int &cur,int lst,int lt,int rt,int pos,int v){
if(pos<lt||pos>rt){
cur=lst;
return ;
}
if(cur==0) cur=++tot,tr[cur].sum=tr[lst].sum;
tr[cur].sum+=v;
tr[cur].sum%=mod;
if(lt==rt) return ;
int mid=(lt+rt)>>1;
insert(tr[cur].ls,tr[lst].ls,lt,mid,pos,v);
insert(tr[cur].rs,tr[lst].rs,mid+1,rt,pos,v);
}
int query(int cur,int lt,int rt,int l,int r){
if(lt>r||rt<l||cur==0) return 0;
if(l<=lt&&rt<=r) return tr[cur].sum;
int mid=(lt+rt)>>1;
return query(ls(cur),lt,mid,l,r)+query(rs(cur),mid+1,rt,l,r)%mod;
}
int qpow(int a,int b){
if(b==0) return 1;
if(b==1) return a%mod;
int res=qpow(a,b/2);
res=res*res%mod;
if(b%2==1) res=res*a%mod;
return res;
}
int h[maxn],L[maxn],R[maxn],res=1,ans;
signed main(){
cin>>n;
for(int i=1;i<=n;i++) cin>>h[i],h[i]++;
for(int i=2;i<=n;i++) cin>>L[i]>>R[i];
res=res*1;
ans+=1;
insert(rt[1],rt[0],1,top,h[1],1);
for(int i=2;i<=n;i++){
int f=((query(rt[R[i]],1,top,1,h[i])-query(rt[L[i]-1],1,top,1,h[i])+mod)%mod)*qpow((R[i]-L[i]+1)%mod,mod-2)%mod;
res=res*(R[i]-L[i]+1)%mod;
ans=(ans+f)%mod;
insert(rt[i],rt[i-1],1,top,h[i],f);
}
cout<<(ans*res)%mod;
}