题意
给你n个蘑菇和m颗大树的位置,以及大树往左倒往右倒的概率,大树的高度,和蘑菇的权值,蘑菇被压倒必死,问你蘑菇不被压死的权值的最大的期望是多少?
思路
对于一颗树而言,他往左倒的概率是
a
a
那么不往左倒的概率就是,那么我们线段树维护一下某个区间不被压倒(树不会倒)的概率就好了,具体怎么维护,我们还是把所有点离散存下来,之后以离散后的点为区间建立线段树节点原来都是1,之后更新每个区间不被压倒的概率就好了,最后我们把权值*概率就行了。
ps:线段树谜之开点,开了尼玛16倍,,,
代码
#include <bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int maxn = 1e5+10;
struct Tree
{
int pos,h;
double l,r;
}Tree[maxn];
struct Mush
{
int pos,val;
}mush[maxn];
int Hash[maxn<<4];
double tree[maxn<<4];
int n , m;
void build(int l,int r,int rt)
{
tree[rt] = 1;
if(l == r) return ;
int m = (l+r)>>1;
build(lson);
build(rson);
}
void update(int L,int R,double val,int l,int r,int rt)
{
if(l>=L && R >= r)
{
tree[rt] *= val;
return ;
}
int m = (l+r)>>1;
if(m >= L) update(L,R,val,lson);
if(R > m) update(L,R,val,rson);
}
double query(int pos,int l,int r,int rt)
{
if(l == r) return tree[rt];
int m = (l+r)>>1;
if(m >= pos) return tree[rt] * query(pos,lson);
else return tree[rt] * query(pos,rson);
}
int main()
{
scanf("%d%d",&n,&m);
int x,y;
int cnt = 0;
for(int i = 0 ; i < n ; i++)
{
scanf("%d%d%d%d",&Tree[i].pos,&Tree[i].h,&x,&y);
Tree[i].l = x/100.0,Tree[i].r = y/100.0;
Hash[cnt++] = Tree[i].pos-1;
Hash[cnt++] = Tree[i].pos + Tree[i].h;
Hash[cnt++] = Tree[i].pos + 1;
Hash[cnt++] = Tree[i].pos - Tree[i].h;
}
for(int i = 0 ; i < m ; i++)
{
scanf("%d%d",&mush[i].pos,&mush[i].val);
Hash[cnt++] = mush[i].pos;
}
sort(Hash,Hash+cnt);
cnt = unique(Hash,Hash+cnt) - Hash;
build(1,cnt,1);
for(int i = 0 ; i < n ; i++)
{
int mid1 = lower_bound(Hash,Hash+cnt,Tree[i].pos-1) - Hash + 1;
int mid2 = lower_bound(Hash,Hash+cnt,Tree[i].pos+1) - Hash + 1;
int l = lower_bound(Hash,Hash+cnt,Tree[i].pos - Tree[i].h) - Hash + 1;
int r = lower_bound(Hash,Hash+cnt,Tree[i].pos + Tree[i].h) - Hash + 1;
update(l,mid1,(1.0-Tree[i].l),1,cnt,1);
update(mid2,r,(1.0-Tree[i].r),1,cnt,1);
}
double ans = 0;
for(int i = 0 ; i < m ; i++)
{
int pos = lower_bound(Hash,Hash+cnt,mush[i].pos) - Hash + 1;
ans += query(pos,1,cnt,1) * mush[i].val;
}
printf("%.10f\n",ans);
}