牛客多校第五场 F take(期望+线段树)

链接:https://www.nowcoder.com/acm/contest/143/F
来源:牛客网
 

题目描述

Kanade has n boxes , the i-th box has p[i] probability to have an diamond of d[i] size.

At the beginning , Kanade has a diamond of 0 size. She will open the boxes from 1-st to n-th. When she open a box,if there is a diamond in it and it's bigger than the diamond of her , she will replace it with her diamond.

Now you need to calculate the expect number of replacements.

You only need to output the answer module 998244353.

Notice: If x%998244353=y*d %998244353 ,then we denote that x/y%998244353 =d%998244353

输入描述:

The first line has one integer n.

Then there are n lines. each line has two integers p[i]*100 and d[i].

输出描述:

Output the answer module 998244353

示例1

输入

复制

3
50 1
50 2
50 3

输出

复制

49912217

题目大意:Kanade有n个宝箱,打开第 i 个宝箱有p[i]的概率开出一个大小为d[i]的宝石。现在Kanade要从编号为1的宝箱开始开,一直开到编号为n的宝箱,一开始Kanade没有宝石,且他不管何时只能拿一个宝石。如果Kanade手中没有宝石,或者宝箱开出的宝石的大小大于Kanade当前拿着的宝石的大小,他都会进行一次交换的操作。现在问当Kanade开完这n个宝箱,他交换宝石次数的期望是多少。

题目思路:对于每个宝石对于答案的贡献都是独立,第 i 个宝石如果可以提供贡献的条件是当且仅当第1~第i-1个宝石中所有大小大于d[i]的宝石都没被开出来,且第 i 个宝石开出来了。那么第 i 个宝石对答案的贡献就可以记为

1*(\prod_{j=1(d[j]>d[i])}^{i-1}(1-p[j]))*p[i]

\prod_{j=1(d[j]>d[i])}^{i-1}(1-p[j])我们可以借助类似线段树查逆序对的方法,先将d[i]进行离散化之后,将(1-p[i])放入线段树中d[i]离散化之后的位置,这样每次查询第 i 位的贡献时只需要求(pos[d[i]],n)的区间乘积就行了。总的复杂度为O(n*logn)(线段树维护的时候记得取模,不然会wa的很惨。不要问我为什么知道。。。)

具体实现看代码:

#include <bits/stdc++.h>
#define fi first
#define se second
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lowbit(x) x&-x
#define pb push_back
#define MP make_pair
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=b;i>=a;i--)
#define clr(a) memset(a,0,sizeof(a))
#define _INF(a) memset(a,0x3f,sizeof(a))
#define FIN freopen("in.txt","r",stdin)
#define fuck(x) cout<<"["<<x<<"]"<<endl
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int>pii;
typedef vector<int> VI;
const int MX=1e5+5;
const int mod=998244353;
const int inf=0x3f3f3f3f;

int n;
int p[MX];
ll d[MX],inv[MX];
vector<ll>has;
int get_id(ll x){
	return lower_bound(has.begin(),has.end(),x)-has.begin()+1;
}
ll tree[MX<<2];
void push_up(int rt){
	tree[rt]=tree[rt<<1]*tree[rt<<1|1]%mod;
}
void build(int l,int r,int rt){
	if(l==r){
		tree[rt]=1;
		return;
	}
	int m=(l+r)>>1;
	build(lson);build(rson);
	push_up(rt);
}
void update(int p,ll d,int l,int r,int rt){
	if(l==r){
		tree[rt]=d;
		return;
	}
	int m=(l+r)>>1;
	if(p<=m) update(p,d,lson);
	else update(p,d,rson);
	push_up(rt);
}
ll query(int L,int R,int l,int r,int rt){
	if(L<=l && r<=R) return tree[rt];
	ll res=1;
	int m=(l+r)>>1;
	if(L<=m) res=(res*query(L,R,lson))%mod;
	if(R>m) res=(res*query(L,R,rson))%mod;
	return res;
}

int main(){
	inv[1]=1;for(int i=2;i<=100;i++) inv[i]=inv[mod%i]*(mod-mod/i)%mod;
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d%lld",&p[i],&d[i]);
		has.pb(d[i]);
	}
	sort(has.begin(),has.end());
	has.erase(unique(has.begin(),has.end()),has.end());
	int sz=has.size();
	build(1,sz,1);
	ll ans=0;
	for(int i=1;i<=n;i++){
		int id=get_id(d[i]);
		ll res=query(id,sz,1,sz,1),tmp=(100-p[i])*inv[100]%mod;
		ans=(ans+res*p[i]%mod*inv[100]%mod+mod)%mod;
		update(id,tmp,1,sz,1);
	}
	printf("%lld\n",ans%mod);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Lee_w_j__/article/details/81367134