列舉每個$S$作為原點,將所有$D$和$T$極角排序。
列舉每個$T$,那麼另一個$T$需要和當前的$T$夾角不超過$180$度,貢獻為內部$D$的個數。
雙指標後用字首和查詢區間的貢獻即可。
時間複雜度$O(n^2\log n)$。
#include<cstdio> #include<algorithm> const int N=810; int D,S,T,i,j,k,cnt,s[N*4],f[N*4],g[N*4];long long ans; struct P{ int x,y,t; P(){} P(int _x,int _y,int _t){x=_x,y=_y,t=_t;} int sgn()const{return x?x>0:y>0;} }a[N],b[N],c[N],e[N*4]; inline bool cmp(const P&a,const P&b){ if(a.sgn()!=b.sgn())return a.sgn()<b.sgn(); return 1LL*a.x*b.y<1LL*a.y*b.x; } int main(){ scanf("%d",&D); for(i=1;i<=D;i++)scanf("%d%d",&a[i].x,&a[i].y); scanf("%d",&S); for(i=1;i<=S;i++)scanf("%d%d",&b[i].x,&b[i].y); scanf("%d",&T); for(i=1;i<=T;i++)scanf("%d%d",&c[i].x,&c[i].y); for(i=1;i<=S;i++){ cnt=0; for(j=1;j<=D;j++)e[++cnt]=P(a[j].x-b[i].x,a[j].y-b[i].y,0); for(j=1;j<=T;j++)e[++cnt]=P(c[j].x-b[i].x,c[j].y-b[i].y,1); std::sort(e+1,e+cnt+1,cmp); for(j=1;j<=cnt;j++)e[j+cnt]=e[j]; for(j=1;j<=cnt*2;j++){ s[j]=s[j-1],f[j]=f[j-1],g[j]=g[j-1]; if(e[j].t)f[j]++,g[j]+=s[j];else s[j]++; } for(j=k=1;j<=cnt;j++)if(e[j].t){ if(k<j)k=j; while(k+1<j+cnt&&1LL*e[j].x*e[k+1].y<=1LL*e[j].y*e[k+1].x)k++; ans+=g[k]-g[j]-s[j]*(f[k]-f[j]); } } return printf("%lld",ans),0; }