思路:我们可以考虑三角剖分,这样问题就变成考虑三角形的选取概率和三角形内有多少个点了。
先用树状数组预处理出三角剖分的三角形中有多少个点,然后用线段树维护,先用原点极角排序,然后枚举i,再以i极角排序,此时线段树的作用就来了,每次到一个询问的教室点,我们就在线段树里面查找之前的概率,统计贡献即可。
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 #define MAXN 2005 7 struct Point{ 8 double x,y; 9 double p,ang; 10 int id; 11 }p[MAXN],Cur[MAXN]; 12 double P[MAXN],T[MAXN * 4]; 13 int n,m,rk[MAXN],s[MAXN],f[MAXN][MAXN]; 14 int read(){ 15 int t=0,f=1;char ch=getchar(); 16 while (ch<‘0‘||ch>‘9‘){if (ch==‘-‘)f=-1;ch=getchar();} 17 while (‘0‘<=ch&&ch<=‘9‘){t=t*10+ch-‘0‘;ch=getchar();} 18 return t*f; 19 } 20 bool cmp(Point p1,Point p2){ 21 return p1.ang<p2.ang; 22 } 23 void build (int k,int l,int r){ 24 if (l==r) {T[k]=1-P[Cur[l].id];return;} 25 int mid=(l+r)>>1; 26 build(k*2,l,mid); 27 build(k*2+1,mid+1,r); 28 T[k]=T[k*2]*T[k*2+1]; 29 } 30 double query(int k,int l,int r,int x,int y){ 31 if (y<l||x>r) return 1.0; 32 if (l==x&&r==y) return T[k]; 33 int mid=(l+r)>>1; 34 if (y<=mid) return query(k*2,l,mid,x,y); 35 else 36 if (x>mid) return query(k*2+1,mid+1,r,x,y); 37 else return query(k*2,l,mid,x,mid)*query(k*2+1,mid+1,r,mid+1,y); 38 } 39 void init(){ 40 n=read();m=read(); 41 for (int i=1;i<=n;i++) 42 scanf("%lf%lf",&p[i].x,&p[i].y),p[i].id=i; 43 for (int i=n+1;i<=n+m;i++) 44 scanf("%lf%lf%lf",&p[i].x,&p[i].y,&P[i]),p[i].id=i; 45 for (int i=1;i<=n+m;i++) 46 p[i].ang=atan2(p[i].y,p[i].x); 47 } 48 void add(int pos){ 49 for (;pos<=n+m;pos+=(pos)&(-pos)) s[pos]++; 50 } 51 int sum(int pos){ 52 int res=0; 53 for (;pos;pos-=(pos)&(-pos)) res+=s[pos]; 54 return res; 55 } 56 void Sort(int mid){ 57 int tot=0; 58 for (int i=0;i<=n+m;i++) 59 if (i!=mid) Cur[++tot]=p[i],Cur[tot].ang=atan2(Cur[tot].y-p[mid].y,Cur[tot].x-p[mid].x); 60 std::sort(Cur+1,Cur+1+tot,cmp); 61 for (int i=1;i<=tot;i++) rk[Cur[i].id]=i; 62 } 63 int range(int l,int r){ 64 if (l<=r) return sum(r)-sum(l-1); 65 return sum(n+m)-sum(l-1)+sum(r); 66 } 67 void solve(){ 68 std::sort(p+1,p+1+n+m,cmp); 69 for (int i=1;i<=n+m+1;i++) 70 if (p[i].id>n){ 71 Sort(i); 72 for (int j=0;j<=n+m;j++) s[j]=0; 73 for (int j=i+1;j<=n+m+1;j++){ 74 if (p[j].id<=n&&p[j].id) add(rk[p[j].id]); 75 f[p[i].id][p[j].id]=std::max(0,range(rk[p[j].id],rk[0])); 76 } 77 for (int j=0;j<=n+m;j++) s[j]=0; 78 for (int j=i-1;j;j--){ 79 if (p[j].id<=n&&p[j].id) add(rk[p[j].id]); 80 f[p[i].id][p[j].id]=std::max(0,range(rk[0],rk[p[j].id])); 81 } 82 } 83 } 84 double ask(int l,int r){ 85 if (l>r) return query(1,1,n+m-1,l,n+m-1)*query(1,1,n+m-1,1,r-1); 86 else return query(1,1,n+m-1,l,r-1); 87 } 88 void linear(){ 89 double ans=0.0; 90 int tot=0; 91 for (int i=1;i<=n+m;i++) 92 if (p[i].id>n){ 93 tot=0; 94 for (int j=1;j<=n+m;j++) 95 if (i!=j) Cur[++tot]=p[j],Cur[tot].ang=atan2(p[j].y-p[i].y,p[j].x-p[i].x); 96 std::sort(Cur+1,Cur+1+tot,cmp); 97 build(1,1,tot); 98 for (int j=1,Pp=1;j<=tot;j++){ 99 for(;(Cur[j].x - p[i].x) * (Cur[Pp].y - p[i].y) - (Cur[j].y - p[i].y) * (Cur[Pp].x - p[i].x) > 0;) Pp=Pp%tot+1; 100 if (Cur[j].id>n){ 101 double pr=ask(Pp,j)*P[p[i].id]*P[Cur[j].id]; 102 if (p[i].x * Cur[j].y - p[i].y * Cur[j].x < 0) 103 ans -= pr * f[p[i].id][Cur[j].id]; else 104 ans += pr * f[p[i].id][Cur[j].id]; 105 } 106 } 107 } 108 printf("%.9lf\n",ans); 109 } 110 int main(){ 111 init(); 112 solve(); 113 linear(); 114 }
时间: 2024-10-18 06:10:10