您的位置:首页 > 其它

FJ省队集训DAY2 T2

2016-07-04 21:57 399 查看








思路:我们可以考虑三角剖分,这样问题就变成考虑三角形的选取概率和三角形内有多少个点了。

先用树状数组预处理出三角剖分的三角形中有多少个点,然后用线段树维护,先用原点极角排序,然后枚举i,再以i极角排序,此时线段树的作用就来了,每次到一个询问的教室点,我们就在线段树里面查找之前的概率,统计贡献即可。

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#define MAXN 2005
struct Point{
double x,y;
double p,ang;
int id;
}p[MAXN],Cur[MAXN];
double P[MAXN],T[MAXN * 4];
int n,m,rk[MAXN],s[MAXN],f[MAXN][MAXN];
int read(){
int t=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-')f=-1;ch=getchar();}
while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
return t*f;
}
bool cmp(Point p1,Point p2){
return p1.ang<p2.ang;
}
void build (int k,int l,int r){
if (l==r) {T[k]=1-P[Cur[l].id];return;}
int mid=(l+r)>>1;
build(k*2,l,mid);
build(k*2+1,mid+1,r);
T[k]=T[k*2]*T[k*2+1];
}
double query(int k,int l,int r,int x,int y){
if (y<l||x>r) return 1.0;
if (x<=l&&r<=y) return T[k];
int mid=(l+r)>>1;
return query(k*2,l,mid,x,y)*query(k*2+1,mid+1,r,x,y);
}
void init(){
n=read();m=read();
for (int i=1;i<=n;i++)
scanf("%lf%lf",&p[i].x,&p[i].y);
for (int i=n+1;i<=n+m;i++)
scanf("%lf%lf%lf",&p[i].x,&p[i].y,&P[i]);
for (int i=1;i<=n+m;i++)
p[i].ang=atan2(p[i].y,p[i].x);
}
void add(int pos){
for (;pos<=n+m;pos+=(pos)&(-pos)) s[pos]++;
}
int sum(int pos){
int res=0;
for (;pos;pos-=(pos)&(-pos)) res+=s[pos];
return res;
}
void Sort(int mid){
int tot=0;
for (int i=0;i<=n+m;i++)
if (i!=mid) Cur[++tot]=p[i],Cur[tot].ang=atan2(Cur[tot].y-p[mid].y,Cur[tot].x-p[mid].x);
std::sort(Cur+1,Cur+1+tot,cmp);
for (int i=1;i<=tot;i++) rk[Cur[i].id]=i;
}
int range(int l,int r){
if (l<=r) return sum(r)-sum(l-1);
return sum(n+m)-sum(l-1)+sum(r);
}
void solve(){
for (int i=1;i<=n+m;i++)
p[i].ang=atan2(p[i].y,p[i].x),p[i].id=i;
std::sort(p+1,p+1+n+m,cmp);
for (int i=1;i<=n+m+1;i++)
if (p[i].id>n){
Sort(i);
for (int j=0;j<=n+m;j++) s[j]=0;
for (int j=i+1;j<=n+m+1;j++){
if (p[j].id<=n&&p[j].id) add(rk[p[j].id]);
f[p[i].id][p[j].id]=std::max(0,range(rk[p[j].id],rk[0]));
}
for (int j=0;j<=n+m;j++) s[j]=0;
for (int j=i-1;j;j--){
if (p[j].id<=n&&p[j].id) add(rk[p[j].id]);
f[p[i].id][p[j].id]=std::max(0,range(rk[0],rk[p[j].id]));
}
}
}
double ask(int l,int r){
if (l>r) return query(1,1,n+m-1,l,n+m-1)*query(1,1,n+m-1,1,r-1);
else return query(1,1,n+m-1,l,r-1);
}
void linear(){
double ans=0.0;
int tot=0;
for (int i=1;i<=n+m;i++)
if (p[i].id>n){
tot=0;
for (int j=1;j<=n+m;j++)
if (i!=j) Cur[++tot]=p[j],Cur[tot].ang=atan2(p[j].y-p[i].y,p[j].x-p[i].x);
std::sort(Cur+1,Cur+1+tot,cmp);
build(1,1,tot);
for (int j=1,Pp=2;j<=tot;j++){
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;
if (Cur[j].id>n){
double pr=ask(Pp,j)*P[p[i].id]*P[Cur[j].id];
if (p[i].x * Cur[j].y - p[i].y * Cur[j].x < 0)
ans -= pr * f[p[i].id][Cur[j].id]; else
ans += pr * f[p[i].id][Cur[j].id];
}
}
}
printf("%.9lf\n",ans);
}
int main(){
init();
solve();
linear();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: