CodeForces 138C Mushroom Gnomes - 2 (线段树)

题意
给你n个蘑菇和m颗大树的位置,以及大树往左倒往右倒的概率,大树的高度,和蘑菇的权值,蘑菇被压倒必死,问你蘑菇不被压死的权值的最大的期望是多少?
思路
对于一颗树而言,他往左倒的概率是 a a 那么不往左倒的概率就是1a,那么我们线段树维护一下某个区间不被压倒(树不会倒)的概率就好了,具体怎么维护,我们还是把所有点离散存下来,之后以离散后的点为区间建立线段树节点原来都是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);

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值