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;
}
posted @ 2024-01-30 23:52  ChiFAN鸭  阅读(61)  评论(0编辑  收藏  举报