[POI 2007] OSI-Axes of Symmetry
\([POI 2007] OSI-Axes of Symmetry\)
这道计算几何非常具有美感,做法很优雅。
首先可以想到通过角和边将整个图形变成一个环。
然后将这个环化成一条链,只需要判断每个长为2n的区间是否为回文即可。
这里可以使用哈希将判断回文的复杂度降至 \(O(1)\)。
(是不是写起来感觉很爽。
#include<bits/stdc++.h>
using namespace std;
#define u unsigned
int T,n,x[100001],y[100001],s[400010];
u int m=8317,p[400001],H1[400001],H2[400001];
int dis(int a,int b,int c,int d){return (a-c)*(a-c)+(b-d)*(b-d);}
int calc(int a,int b,int c){return (x[a]-x[b])*(y[b]-y[c])-(x[b]-x[c])*(y[a]-y[b]);}
bool check(int l, int r){
u int k=H1[r]-H1[l-1]*P[r-l+1];
u int t=H2[l]-H2[r+1]*P[r-l+1];
return k==t;
}
int main(){
ios::sync_with_stdio(0),cin.tie(0);
p[0]=1;
for(int i=1;i<400001;i++)p[i]=p[i-1]*m;
cin>>T;
while(T--){
cin>>n;
for(int i=1;i<=n;i++)cin>>x[i]>>y[i];
for(int i=1;i<=n;i++){
int a=i,b=i%n+1,c=(i+1)%n+1;
s[i*2-1+2*n]=s[i*2-1]=dis(x[a],y[a],x[b],y[b]),s[i*2+n*2]=s[i*2]=clac(a,b,c);
}
for(int i=1;i<=n*4;i++)H1[i]=H1[i-1]*m+s[i];
for(int i=n*4;i>=1;i--)H2[i]=H2[i+1]*m+s[i];
int ans=0;
for(int i=1;i<=n*2;i++)ans+=ck(i,i+n*2);
cout<<ans/2<<'\n';
}
return 0;
}

浙公网安备 33010602011771号