BZOJ4814,几何

对每个关键点i,将每个三角形缩成一个线段(因为三角形不相交),然后把线段两端点 和其他关键点一起 以i为中心点 极角排序。

扫一圈。扫到一个关键点j时, 判断当前最靠近i的线段是否遮盖i到j的路径,  因为对同一个点i,线段之间的相对关系是不变的,所以可以用堆维护加线段删线段,

 1 #include <bits/stdc++.h>
 2 #define LL long long
 3 using namespace std;
 4 int T,n,m,p,q,k,t,x,y,z,ans,d[2005],e[1005];
 5 struct node{int x,y,d;}a[4005],b[4005],c[1005][3];
 6 LL operator *(node a,node b){return (LL)a.x*b.y-(LL)a.y*b.x;}
 7 node operator -(node a,node b){return (node){a.x-b.x,a.y-b.y,a.d};}
 8 bool hi(int u,int v){ // v是不是比u更接近中心点
 9     LL x=(c[v][0]-c[u][0])*(c[u][2]-c[u][0]),y=(c[v][2]-c[u][0])*(c[u][2]-c[u][0]);
10     if (x>=0&&y>=0) return 0; if (x<=0&&y<=0) return 1;
11     return (c[u][0]-c[v][0])*(c[v][2]-c[v][0])>=0&&(c[u][2]-c[v][0])*(c[v][2]-c[v][0])>=0;
12 }
13 bool cmp(node u,node v){ LL x=(u-a[1])*(v-a[1]); if (!x) return u.d>v.d; else return x>0;}
14 void join(int x){
15     int i=++T;
16     while (i>1&&hi(d[i>>1],x)) e[d[i]=d[i>>1]]=i,i>>=1;
17     d[i]=x; e[x]=i;
18 }
19 void del(int x){
20     if (e[x]==T) {e[x]=d[T--]=0; return;}
21     int i=e[x]; e[x]=0; x=d[i]=d[T]; d[T--]=0;
22     while (i>1&&hi(d[i>>1],x)) e[d[i]=d[i>>1]]=i,i>>=1;
23     while (i<<1<=T&&hi(x,d[i<<1])||i<<1<T&&hi(x,d[i<<1^1]))
24     i<<1==T||hi(d[i<<1^1],d[i<<1])?
25     (e[d[i]=d[i<<1]]=i,i<<=1):(e[d[i]=d[i<<1^1]]=i,i=i<<1^1);
26     d[i]=x; e[x]=i;
27 }
28 int main(){
29     scanf("%d%d",&n,&m); if (n==1) {puts("0"); return 0;}
30     for (t=1;t<=n;++t) scanf("%d%d",&a[t].x,&a[t].y);
31     for (int i=1;i<=m;++i)
32         for (int j=0;j<3;++j)
33         a[++t].d=i,scanf("%d%d",&a[t].x,&a[t].y),c[i][j]=a[t];
34     t=n+m+m;
35     for (int i=1;i<=n;++i){
36         while (T) e[d[T]]=0,d[T--]=0;
37         swap(a[i],a[1]); p=1; q=t+1; b[1]=a[1];
38         for (int j=2;j<=n;++j) a[j].x<a[1].x?b[++p]=a[j]:b[--q]=a[j];
39         for (int j=1;j<=m;++j){
40             sort(c[j],c[j]+3,cmp);
41             c[j][0].x<a[1].x?b[++p]=c[j][0]:b[--q]=c[j][0];
42             c[j][2].x<a[1].x?(b[++p]=c[j][2],b[p].d*=-1):(b[--q]=c[j][2],b[q].d*=-1);
43         }    
44         if (2<=p) sort(b+2,b+p+1,cmp); 
45         if (p<t)sort(b+p+1,b+t+1,cmp);
46         for (int j=1;j<=m;++j) 
47          if ((c[j][0]-a[1])*(b[2]-a[1])>0&&(c[j][2]-a[1])*(b[2]-a[1])<=0) join(j);
48         for (int j=2;j<=t;++j)
49             if (!b[j].d){
50                 if (!T||(c[d[1]][2]-c[d[1]][0])*(b[j]-c[d[1]][0])>0) ++ans;
51             }else
52             if (b[j].d>0) join(b[j].d); else del(-b[j].d);
53     }
54     printf("%d",ans>>1);
55     return 0;
56 }
秋姉妹のなく頃に

n^2*log*计算几何自带大常数。。。然而跑的还算挺快的

原文地址:https://www.cnblogs.com/cyz666/p/6811634.html