codeforce 139E

成段更新+离散化才能过,数据好强。。

单点更新挂在了test27,下次做到成段更新再来做!

 
 
/*
期望=存活概率*点权值/100
ans=sum(期望)
离散化树木权值,数轴统计累加可能倒下的树木概率(直接加权值即可)
线段树单点,sum[rt]维护在这个区间中所有蘑菇的存活期望值
*/
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define maxn 100005
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define ll long long 
using namespace std;
struct Tree{
    int pos,h,pl,pr;//坐标,高度,左概率,右概率
}tree[maxn];
struct Mushroom{
    int pos,w;//蘑菇坐标,蘑菇权值
}mushroom[maxn];
int axis[maxn<<3],cnt,tot;
double poss[maxn<<3];//排序后的坐标点,数轴[1,maxn<<3]上存活概率
double sum[maxn<<2];
void build(int l,int r,int rt){
    sum[rt]=0;
    if(l==r)
        return;
    int m=l+r>>1;
    build(lson);
    build(rson);
}
inline pushup(int rt){
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void update(int pos,double val,int l,int r,int rt){
    sum[rt]+=val;
    if(l==r) return;
    int m=l+r>>1;
    if(pos<=m) update(pos,val,lson);
    else update(pos,val,rson);
}
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    cnt=0;
        for(int i=1;i<=n;i++){
            scanf("%d%d%d%d",&tree[i].pos,&tree[i].h,&tree[i].pl,&tree[i].pr);
            axis[cnt++]=tree[i].pos;
            axis[cnt++]=tree[i].pos-tree[i].h;
            axis[cnt++]=tree[i].pos+tree[i].h;
        }
        for(int i=1;i<=m;i++){
            scanf("%d%d",&mushroom[i].pos,&mushroom[i].w);
            axis[cnt++]=mushroom[i].pos;
        }
    
        sort(axis,axis+cnt);
        int tot=unique(axis,axis+cnt)-axis;//离散化
        for(int i=1;i<=tot;i++)//一开始所有的坐标上存活概率都是1
            poss[i]=1;
        //每个点找坐标logn,打标记最多n,复杂度O(n*n)
        for(int i=1;i<=n;i++){
            int pos=lower_bound(axis,axis+tot,tree[i].pos)-axis+1;
            int posl=lower_bound(axis,axis+tot,tree[i].pos-tree[i].h)-axis+1;
            int posr=lower_bound(axis,axis+tot,tree[i].pos+tree[i].h)-axis+1;
            for(int j=posl;j<pos;j++)//倒在左区间的概率
                poss[j]*=1-(double)tree[i].pl/100;
            for(int j=pos+1;j<=posr;j++)//倒在右区间的概率
                poss[j]*=1-(double)tree[i].pr/100;
        }
        //至此统计完概率,开始建立线段树
        build(1,tot,1);
        for(int i=1;i<=m;i++){
            int pos=lower_bound(axis,axis+tot,mushroom[i].pos)-axis+1;
            update(pos,mushroom[i].w*poss[pos],1,tot,1);//把权值*期望更新到线段树中
        }
        printf("%.4lf\n",sum[1]);
    
    return 0;
}
 
  
 
 

猜你喜欢

转载自www.cnblogs.com/zsben991126/p/9901990.html