洛谷传送门
BZOJ传送门
题目大意
给你一个多边形(不保证是凸的), 要求求出其对称轴数量。
输入输出格式
输入格式
第一行一个整数 T T , 表示有组数据。
对于每组数据, 第一行一个整数 N N , 表示有个顶点。
一下 N+1 N + 1 行, 每行两个整数 xi,yi x i , y i ,表示多边形上一个点的坐标。坐标按顺时针方向给出,保证是多边形上的一个顶点(即任意连续三个点不共线)。
输出格式
一共 T T 行,每行一个整数表示多边形的对称轴数量。
输入输出样例
输入样例#1:
2
12
1 -1
2 -1
2 1
1 1
1 2
-1 2
-1 1
-2 1
-2 -1
-1 -1
-1 -2
1 -2
6
-1 1
-2 0
-1 -1
1 -1
2 0
1 1
输出样例#1:
4
2
数据范围
。
解题分析
几何直接搞不是很好办, 我们将边、角哈希一下变成序列, 然后就成了一个找回文长度 ≥N×2 ≥ N × 2 的回文串个数的字符串题目了…
注意到这是一个环上的问题, 所以要将序列复制一份接在后面。
一开始写了个假的 Manacher M a n a c h e r 结果还能得 70 70 分…
代码如下:
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <algorithm>
#define R register
#define IN inline
#define W while
#define MX 500050
#define gc getchar()
#define db double
#define EPS 1e-5
#define MOD 1000000007
bool neg;
template <class T>
IN void in(T &x)
{
x = 0; R char c = gc;
W (!isdigit(c))
{if(c == '-') neg = true; c = gc;}
W (isdigit(c))
x = (x << 3) + (x << 1) + c - 48, c = gc;
if(neg) neg = false, x = -x;
}
int seq[MX << 2];
int ans[MX << 3], cnt;
struct Pt
{int x, y;}pt[MX];
IN int operator * (const Pt &x, const Pt &y)
{return (1ll * (x.x * y.y - x.y * y.x) % MOD + MOD) % MOD;}
IN Pt operator - (const Pt &x, const Pt &y)
{return {x.x - y.x, x.y - y.y};}
int T, dot, tot;
IN int dis(const Pt &x, const Pt &y)
{return 1ll * ((x.x - y.x) * (x.x - y.x) + (x.y - y.y) * (x.y - y.y)) % MOD;}
IN int getang(const int &lef)//直接返回叉积也行, double太慢
{return 1ll * ((pt[lef] - pt[lef + 1]) * (pt[lef + 2] - pt[lef + 1])) % MOD;}
void Manacher_init()
{
int bd = dot << 1, tar = dot - 1;
seq[tot = 0] = -999;
R int mid = 0, pos = 0; bd = dot << 1;
for (R int i = 1; i <= bd; ++i)
{
if(i < pos) ans[i] = std::min(pos - i, ans[2 * mid - i]);
else ans[i] = 1;
W (seq[i - ans[i]] == seq[i + ans[i]]) ++ans[i];
if(pos < i + ans[i]) pos = i + ans[i], mid = i;
if(ans[i] - 1 > tar) ++tot;
}
}
int main(void)
{
in(T); int bd, step;
W (T--)
{
in(dot);
for (R int i = 1; i <= dot; ++i)
in(pt[i].x), in(pt[i].y);
pt[dot + 1] = pt[1], pt[dot + 2] = pt[2];
for (R int i = 1; i <= dot; ++i)
{
seq[(i << 1) - 1] = dis(pt[i], pt[i + 1]);
seq[i << 1] = getang(i);
} bd = dot << 2; step = dot << 1;
for (R int i = dot << 1 | 1; i <= bd; ++i) seq[i] = seq[i - step];
Manacher_init();
printf("%d\n", tot);
}
}