【HNOI2016模拟4.4】Stage

来源:互联网 发布:蒙古作文软件 编辑:程序博客网 时间:2024/06/06 13:17

Description

这里写图片描述
N,M<=1e3

Solution

考虑每个点被观察到的概率
这样很难算我们可以计算每个点不被观察到的概率
这个等价于把这个点和所有观察点拉出来一起做凸包,这个点出现在凸包上的概率
那么我们可以枚举两条边,计算这两条边出现的概率
就是这两条边外部的点全部不出现
这些点把所有观察点关于这个点做极角排序后是连续的一段
所以可以用一个数据结构维护一段点的(1-p)的积
然后观察答案式子发现是可以线性做的
为了避免算重强制第二条边都在第一条边的左手系

Code

#include <cmath>#include <cstdio>#include <cstring>#include <algorithm>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,a,b) for(int i=a;i>=b;i--)using namespace std;typedef long long ll;typedef double db;const int N=1e3+5;int n,m;db ans,sum[N][10],pre[N],suf[N];struct DOT{int x,y;db p;}a[N],p[N],rt;ll cro(DOT x,DOT y,DOT rt) {    return (ll)(x.x-rt.x)*(y.y-rt.y)-(ll)(x.y-rt.y)*(y.x-rt.x);}bool cmp(DOT x,DOT y) {    return atan2(x.y-rt.y,x.x-rt.x)<atan2(y.y-rt.y,y.x-rt.x);}db get_sum(int l,int r) {    if (l>r) return 1;    db res=1;    fd(j,9,0)        if (l+(1<<j)<=r)                res*=sum[l][j],l+=(1<<j);    return res*sum[r][0];}int main() {    scanf("%d%d",&n,&m);    fo(i,1,n) scanf("%d%d",&a[i].x,&a[i].y);    fo(i,1,m) scanf("%d%d%lf",&p[i].x,&p[i].y,&p[i].p);    fo(i,1,n) {        rt=a[i];        sort(p+1,p+m+1,cmp);        db now=0;ans+=1;        fo(j,1,m) sum[j][0]=1-p[j].p;        fo(k,1,9)            fo(j,1,m-(1<<(k-1)))                sum[j][k]=sum[j][k-1]*sum[j+(1<<(k-1))][k-1];        pre[0]=1;fo(j,1,m) pre[j]=pre[j-1]*(1-p[j].p);        suf[m+1]=1;fd(j,m,1) suf[j]=suf[j+1]*(1-p[j].p);        fo(j,1,m) ans-=pre[j-1]*suf[j+1]*p[j].p;ans-=pre[m];        int k=1;        while (k<m&&cro(p[k+1],p[1],rt)<0) {            ++k;            now+=get_sum(k+1,m)*p[k].p;        }        ans-=now*p[1].p;if (k==1) k++;        fo(j,2,m) {            if (cro(p[j-1],p[j],rt)>=0) now-=get_sum(1,j-2)*get_sum(j+1,m)*p[j].p;            now*=(1-p[j-1].p);            while (k%m+1!=j&&cro(p[k%m+1],p[j],rt)<0) {                k=k%m+1;                if (j<k) now+=get_sum(1,j-1)*get_sum(k+1,m)*p[k].p;                else now+=get_sum(k+1,j-1)*p[k].p;            }            ans-=now*p[j].p;            if (j==k) k++;        }    }    printf("%.6lf\n",ans);}
原创粉丝点击