卧薪尝胆,厚积薄发。
POI2007 OSI-Axes of Symmetry
Date: Fri Mar 29 20:00:30 CST 2019 In Category: NoCategory

Description:

给定一个多边形,求对称轴数量。
$1\leqslant n\leqslant 10^5$

Solution:

按顺时针把边和角放到一个数组里倍长,那么如果有一个长度为 $2n+1$ 的奇回文串就合法, $manacher$ 即可。

Code:


#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cctype>
#include<cstring>
using namespace std;
inline int rd()
{
register int res = 0,f = 1;register char c = getchar();
while(!isdigit(c)){if(c == '-')f = -1;c = getchar();}
while(isdigit(c))res = (res << 1) + (res << 3) + c - '0',c = getchar();
return res * f;
}
int n;
#define MAXN 400010
int c[MAXN];
typedef long long ll;
ll x[MAXN],y[MAXN];
struct state
{
int val,tp;
}s[MAXN];
bool operator == (state a,state b){return (a.val == b.val && a.tp == b.tp);}
ll dis(int a,int b){return (x[a] - x[b]) * (x[a] - x[b]) + (y[a] - y[b]) * (y[a] - y[b]);}
ll cross(int a,int b,int c){return (x[b] - x[a]) * (y[c] - y[b]) - (y[b] - y[a]) * (x[c] - x[b]);}
int h[MAXN];
void work()
{
scanf("%d",&n);
for(int i = 1;i <= n;++i)scanf("%d%d",&x[i],&y[i]);
int tot = 0;
for(int i = 1;i <= n;++i)
{
int nxt = i % n + 1,nxtt = (i + 1) % n + 1;
s[++tot] = (state){dis(i,nxt),1};
s[++tot] = (state){cross(i,nxt,nxtt),2};
}
for(int i = 2 * n + 1;i <= 4 * n;++i)s[i] = s[i - 2 * n];
tot = 4 * n - 1;
int maxr = 0,pos;
int ans = 0;
for(int i = 1;i <= tot;++i)
{
if(maxr > i)h[i] = min(h[2 * pos - i],maxr - i + 1);
else h[i] = 1;
while(i - h[i] >= 1 && i + h[i] <= 4 * n && s[i - h[i]] == s[i + h[i]])++h[i];
if(i + h[i] - 1 > maxr)
{
maxr = i + h[i] - 1;
pos = i;
}
ans += (h[i] >= n);
}
cout << ans / 2 << endl;
return;
}
int main()
{
int testcases = rd();
while(testcases--)work();
return 0;
}
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡