P7553

· · 题解

通过观察可以发现: 一条线段 AB 被另一条线段 CD 穿过等价于四边形 ADBC 是凸的。

考虑通过计数来代替判定,定义 all[A][B] 表示以 AB 为对角线的四边形个数,aot[A][B] 表示以 AB 为对角线且 \angle A\geqslant\pi 的凹四边形个数。

aot[A][B]+aot[B][A]=all[A][B]=all[B][A] 时表示 AB 是满足条件的边,实际意义为以 AB 为对角线的四边形全为凹四边形。

目前为止问题已经转化成如何求 aotall

![](https://cdn.luogu.com.cn/upload/image_hosting/3felozt2.png?x-oss-process=image/resize,m_lfit,h_170,w_225) $aot$ 的计算同样枚举一个点 $A$,对剩下的点进行极角排序,枚举到一个点 $B$ ,找到所有的 $(C,D)$ 使得 $\angle BAC\leqslant\pi$ 且 $\angle CAD\leqslant\pi$ 且 $\angle BAD\leqslant\pi$ 的合法对数即可。 ![](https://cdn.luogu.com.cn/upload/image_hosting/uby515gd.png?x-oss-process=image/resize,m_lfit,h_170,w_225) 具体细节可以看代码 ```c #include<bits/stdc++.h> #define title "title" #define ll long long #define ull unsigned ll #define fix(x) fixed<<setprecision(x) #define pii pair<int,int> #define vint vector<int> #define pb push_back #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define red(i,a,b) for(int i=(a);i>=(b);i--) #define Help freopen("a","r",stdin) #define db double #define ld long db #define vii vector<pii> #define fi first #define se second #define mp make_pair using namespace std; void Freopen() { freopen(title".in","r",stdin); freopen(title".out","w",stdout); } int read() { int g=0,f=1; char ch=getchar(); while(ch<'0'||'9'<ch){if(ch=='-')f=-1;ch=getchar();} while('0'<=ch&&ch<='9'){g=g*10+ch-'0';ch=getchar();} return g*f; } const int N=1005; const db pi=acos(-1); pair<db,int>st[N<<1]; pii p[N]; int n,su[N<<1],all[N][N],aot[N][N]; signed main() { n=read(); rep(i,1,n) { int x=read(),y=read(); p[i]=pii(x,y); } rep(i,1,n) { int cnt=0; rep(j,1,n)if(i!=j)st[++cnt]=mp(atan2(p[j].se-p[i].se,p[j].fi-p[i].fi),j); sort(st+1,st+cnt+1); rep(j,1,cnt)st[j+cnt]=st[j],st[j+cnt].fi+=pi*2; int k=1; rep(j,1,cnt) { while(st[k+1].fi-st[j].fi<=pi)k++; su[j+cnt]=su[j]=k-j; all[i][st[j].se]=su[j]*(cnt-1-su[j]); } rep(j,1,cnt<<1)su[j]+=su[j-1]; k=1; rep(j,1,cnt) { while(st[k+1].fi-st[j].fi<=pi)k++; aot[i][st[j].se]=su[k]-su[j]-(k-j)*(k-j-1)/2; } } int Ans=0; rep(i,1,n)rep(j,i+1,n)if(aot[i][j]+aot[j][i]==all[i][j])Ans++; cout<<Ans; return signed(); } ```