成段更新+离散化才能过,数据好强。。
单点更新挂在了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 ",sum[1]); return 0; }