2020暑期牛客多校训练营第九场(C)Groundhog and Gaming Time(数学期望,线段树,逆元)

Groundhog and Gaming Time

原题请看这里

题目描述;

P K U W C 2019 d a y 2 PKUWC2019day2 晚上, n {n} 个同学包括 S o e t d i t T X 1145967673 Z P A Y A U R G r o u n d h o g Soetdit,TX1145967673,ZPAYAUR,Groundhog 做出了一个了不起的决定:他们准备参加一个车队,他们将分担一夜直到黎明。
那天晚上,他们一个接一个地上网。第 [ i ] [i] 个同学将从 [ L i R i ] [L_i,R_i] 上线。但是有人报告了一条消息:他们的老师晚上会来。每个人都有 1 2 \frac{1} {2} 的可能性来接收消息,而接收到该消息的人将不会在晚上上网。他们的可用游戏时间是所有游戏者都在线时。因此,他们开始思考一个问题:对他们的可用时间模的平方的期望是什么 998244353 {998244353}
简化的问题:有 n {n} 个段 [ L i R i ] [L_i,R_i] ,每个段都有可能选择 1 2 \frac {1} {2} ,问题是计算 [ L a 1 , R a 1 ] [ L a 2 R a 2 ] [ L a m R a m ] 2 | [L_ {a_1},R_ {a_1}] \cap [L_ {a_2},R_ {a_2}] \cap \cdots \cap [L_ {a_m},R_ {a_m}] | ^ 2 m o d mod 998244353 {998244353} 的期望值。 a i a_i 表示选定的第 i t h {i ^ {th}} 个段的数量。

输入描述:

第一行包含一个整数 n {n} ,表示学生人数。
接下来的 n {n} 行分别包含两个整数 L i R i L_i,R_i ,这表示第 i i 个学生的游戏时间。

输出描述:

输出一行包含答案模 998244353 {998244353}

样例输入:

6
2 2
1 2
1 4
1 5
3 5
3 6

样例输出:

405536771

思路:

求期望的方法有很多种,这题我们选择期望dp求期望的方法。
首先由于数据较大我们需要先对数据进行离散化,然后我们按左右端点升序排序并考虑每一段对答案的贡献。
我们设区间A出现在b条线段中,则有:
P ( A ) = 2 a 1 2 n P(A)=\frac{2^a-1}{2^n}
应为不能全选,所以要减一。
所以: E ( A ) = 2 a 1 2 n A ( E(A)=\frac{2^a-1}{2^n}*|A|( 听说两个‘|’还可以表示size ) )
那么在所有 n n 条线段中 P i P_i 的贡献 ( a i (a_i 条线段包含 A ) A)
E ( Q ) P i \sum E(Q)*|P_i|
= j ( 2 b j 1 2 n Q j ) P i =\sum_j(\frac{2^{b_j}-1}{2^n}*|Q_j|)*|P_i|
= j ( 2 b j 2 n Q j ) P i P i m x =\sum_j(\frac{2^{b_j}}{2^n}*|Q_j|)*|P_i|-|P_i|*mx
我们可以用线段树来维护 2 b i 2^{b_i} ,最后除以 2 n 2^n 并减去 m x mx 即可
具体细节请看代码。

A C AC C o d e Code :

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int mod = 998244353;
const int MAXN = 1e6+5;
const int N = 1e9 + 1;
ll a[MAXN << 2], b[MAXN << 2], trl[MAXN], trr[MAXN], l[MAXN];
ll r[MAXN], lsh[MAXN], cnt, ans;
int n;
ll ksm (ll a, ll b) {
	ll ret = 1;
	while (b){
		if(b & 1) ret = ret * a % mod;
		a = a * a % mod;
		b >>= 1;
	}
	return ret;
}//快速幂求逆元 
bool cmp1 (int x, int y){ return l[x] < l[y]; }
bool cmp2 (int x, int y){ return r[x] < r[y]; }
void build_tree (int pos, int l, int r){//建线段树 
	a[pos] = lsh[r + 1] - lsh[l];
	b[pos] = 1;
	if (l == r) return;
	int mid = l + r >> 1;
	build_tree (pos << 1, l, mid);
	build_tree (pos << 1 | 1, mid + 1, r);
}
void f (int pos, int l, int r, ll num, int x, int y){//将区间[l,r]的权值都*num 
	if(l <= x && r >= y){
		a[pos] = a[pos] * num % mod;
		b[pos] = b[pos] * num % mod;
		return;
	}
	int mid = x + y >> 1;
	if (l <= mid) f (pos << 1, l, r, num, x, mid);
	if (r > mid) f (pos <<1 | 1, l, r, num, mid + 1, y);
	a[pos] = (a[pos << 1] + a[pos << 1 | 1]) * b[pos] % mod;//b[pos]就是lazy标记,这里可以不用下推标记。 
}
int main (){
	lsh[1] = 0;
	lsh[2] = N;//添加最左最优的端点,用于处理所有线段都不选择的情况 
	cnt = 2;
	scanf ("%d", &n);
	for (int i = 1; i <= n; ++i){
		scanf("%lld%lld", l + i ,r + i);
		lsh[++cnt] = l[i];
		lsh[++cnt] = ++r[i];
	}
	sort (lsh + 1, lsh + cnt + 1);
	cnt = unique(lsh + 1, lsh + cnt + 1) - lsh - 1;//离散化 
	build_tree(1, 1, cnt - 1);//建线段树,i点的初始权值为区间[i,i+1]的长度 
	for (int i = 1; i <= n; ++i){
		l[i] = lower_bound(lsh + 1, lsh + cnt + 1, l[i]) - lsh;//映射到原值 
		r[i] = lower_bound(lsh + 1, lsh + cnt + 1, r[i]) - lsh;
	}
	for (int i = 1; i <= n; ++i) trl[i] = trr[i] = i;
	sort (trl + 1, trl + n + 1, cmp1);//线段按左端点排序 
	sort (trr + 1, trr + n + 1, cmp2);//线段按右端点排序 
	int t1 = 1, t2 = 1; 
	for (int i = 1; i < cnt; ++i){//遍历区间[i,i+1],维护包含该区间的线段的交集的期望。这个期望通过计算所有区间的贡献和得到
	//从m的线段,找出a个线段包含区间[i,i+1]。计算这a个线段的交集的期望,等于每个期间的贡献总和。
	//a个线段,有b个线段覆盖区间[j,j+1],则区间[j,j+1]的贡献=长度*(2^b-1)/2^n。其中-1和/2^n最后再去除 
		for (; t1 <= n && l[trl[t1]] <= i; ++t1)//添加左端点小于等于i的线段的贡献 
			f(1, l[trl[t1]], r[trl[t1]] - 1, 2, 1, cnt - 1);//添加贡献,等于该区间的权值*2 
		for (;t2 <= n && r[trr[t2]] <= i; ++t2)//删除右端点小于等于i的线段的贡献 
			f(1, l[trr[t2]], r[trr[t2]] - 1, ksm(2, mod - 2), 1, cnt - 1);//添加贡献,等于该区间的权值-2 
		ans = (ans + a[1] * (lsh[i + 1] - lsh[i])) % mod;//计入答案,此时ans=sum(方案权值*方案数) 
	}//注意此时统计完时,未减去考虑所有线段都不选择的情况,即贡献=长度*(2^b-1)/2^n中的-1 
	ans = (ans + mod - 1ll * N * N % mod) % mod;//减去所有线段都不选择的情况 
	for (int i = 1; i <= n; ++i)
		ans = ans * ksm(2, mod - 2) % mod;//除2^n,得到期望 
	printf("%lld\n", ans);
}

猜你喜欢

转载自blog.csdn.net/s260127ljy/article/details/107898287