Description
Solution
把边和角顺次放入一个数组里,如果一个点为中心的回文串的半径大于(n),那就一定是一个对称轴。跑一遍manacher就行。
Code
#include <algorithm>
#include <cmath>
#include <cstdio>
using std::max;
typedef long double ld;
typedef long long ll;
const int N = 4e5 + 10;
const double eps = 1e-8;
struct point {
ll x, y;
point(ll x = 0, ll y = 0) : x(x), y(y) {}
} p[N];
int n, ans[N];
struct state {
double x;
ll md;
state(double x = 0, ll md = 0) : x(x), md(md) {}
bool operator==(const state &a) const {
return md == a.md && fabs(x - a.x) < eps;
}
} f[N];
inline double dis(const point &x, const point &y) {
return sqrt((x.x - y.x) * (x.x - y.x) + (x.y - y.y) * (x.y - y.y));
}
inline double cross(const point &x, const point &y, const point &z) {
return 1.0 * (y.x - x.x) * (z.y - y.y) - 1.0 * (z.x - y.x) * (y.y - x.y);
}
int main() {
#ifdef WYXLOCAL
freopen("tmp.in", "r", stdin);
freopen("tmp.out", "w", stdout);
#endif // WYXLOCAL
int t;
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf("%lld%lld", &p[i].x, &p[i].y);
}
p[0] = p[n];
p[n + 1] = p[1];
for (int i = 0; i < n; ++i) {
f[i * 2] = state(dis(p[i], p[i + 1]), 1);
f[i * 2 + 1] = state(cross(p[i], p[i + 1], p[i + 2]), 2);
}
for (int i = 0; i < n * 2; ++i) f[n * 2 + i] = f[i];
f[n * 4] = state(0, 0);
int mxr = 0, pos = 0;
for (int i = 0; i < 4 * n; ++i) {
if (i < mxr)
ans[i] = std::min(ans[2 * pos - i], mxr - i + 1);
else
ans[i] = 1;
while (ans[i] <= i && f[i + ans[i]] == f[i - ans[i]]) ans[i]++;
if (i + ans[i] - 1 > mxr) {
mxr = i + ans[i] - 1;
pos = i;
}
}
int cnt = 0;
for (int i = 0; i < 4 * n; ++i)
if (ans[i] > n) cnt++;
printf("%d
", cnt / 2);
}
return 0;
}