diff --git a/OnlineJudges/poj/2187.cpp b/OnlineJudges/poj/2187.cpp new file mode 100644 index 0000000..bc08067 --- /dev/null +++ b/OnlineJudges/poj/2187.cpp @@ -0,0 +1,53 @@ +#include +#include +inline int max(int a, int b) { return a > b ? a : b; } +const int N = 50005; +struct point +{ + int x, y; + point() {} + point(int _x, int _y) : x(_x), y(_y) {} +}a[N], stk[N]; +#define pArg(x) const point &x +inline point operator+(pArg(l), pArg(r)) { return point(l.x + r.x, l.y + r.y); } +inline point operator-(pArg(l), pArg(r)) { return point(l.x - r.x, l.y - r.y); } +inline int cross(pArg(l), pArg(r)) { return l.x * r.y - l.y * r.x; } +inline int dot(pArg(l), pArg(r)) { return l.x * r.x + l.y * r.y; } +inline int len2(pArg(p)) { return p.x * p.x + p.y * p.y; } +inline bool cmp1(pArg(l), pArg(r)) { return l.x < r.x || (l.x == r.x && l.y < r.y); } +inline bool cmp2(pArg(l), pArg(r)) +{ + int det = cross(l - a[0], r - a[0]); + return det != 0 ? det > 0 : len2(l - a[0]) < len2(r - a[0]); +} +#define nxt(x) ((x) == n - 1 ? 0 : (x) + 1) +#define area(p, u, v) cross(u - p, v - p) +int main() +{ + int n; + scanf("%d", &n); + for (int i = 0; i < n; i++) + scanf("%d%d", &a[i].x, &a[i].y); + std::swap(a[0], *std::min_element(a, a + n, cmp1)); + std::sort(a + 1, a + n, cmp2); + int top = 0; + for (int i = 0; i < n; i++) + { + while (top >= 2 && cross(a[i] - stk[top - 1], stk[top - 1] - stk[top - 2]) >= 0) top--; + stk[top++] = a[i]; + } + stk[top] = stk[0]; + int res = 0; + if (top == 2) + res = len2(stk[1] - stk[0]); + else for (int i = 0, j = 2; i < n; i++) + { + while (nxt(j) != i && + area(stk[j], stk[i], stk[i + 1]) <= + area(stk[j + 1], stk[i], stk[i + 1])) + j = nxt(j); + res = max(res, max(len2(stk[j] - stk[i]), len2(stk[j] - stk[i + 1]))); + } + printf("%d", res); + return 0; +} \ No newline at end of file diff --git a/省选准备/assets/day5/poj2187.cpp b/省选准备/assets/day5/poj2187.cpp new file mode 100644 index 0000000..bc08067 --- /dev/null +++ b/省选准备/assets/day5/poj2187.cpp @@ -0,0 +1,53 @@ +#include +#include +inline int max(int a, int b) { return a > b ? a : b; } +const int N = 50005; +struct point +{ + int x, y; + point() {} + point(int _x, int _y) : x(_x), y(_y) {} +}a[N], stk[N]; +#define pArg(x) const point &x +inline point operator+(pArg(l), pArg(r)) { return point(l.x + r.x, l.y + r.y); } +inline point operator-(pArg(l), pArg(r)) { return point(l.x - r.x, l.y - r.y); } +inline int cross(pArg(l), pArg(r)) { return l.x * r.y - l.y * r.x; } +inline int dot(pArg(l), pArg(r)) { return l.x * r.x + l.y * r.y; } +inline int len2(pArg(p)) { return p.x * p.x + p.y * p.y; } +inline bool cmp1(pArg(l), pArg(r)) { return l.x < r.x || (l.x == r.x && l.y < r.y); } +inline bool cmp2(pArg(l), pArg(r)) +{ + int det = cross(l - a[0], r - a[0]); + return det != 0 ? det > 0 : len2(l - a[0]) < len2(r - a[0]); +} +#define nxt(x) ((x) == n - 1 ? 0 : (x) + 1) +#define area(p, u, v) cross(u - p, v - p) +int main() +{ + int n; + scanf("%d", &n); + for (int i = 0; i < n; i++) + scanf("%d%d", &a[i].x, &a[i].y); + std::swap(a[0], *std::min_element(a, a + n, cmp1)); + std::sort(a + 1, a + n, cmp2); + int top = 0; + for (int i = 0; i < n; i++) + { + while (top >= 2 && cross(a[i] - stk[top - 1], stk[top - 1] - stk[top - 2]) >= 0) top--; + stk[top++] = a[i]; + } + stk[top] = stk[0]; + int res = 0; + if (top == 2) + res = len2(stk[1] - stk[0]); + else for (int i = 0, j = 2; i < n; i++) + { + while (nxt(j) != i && + area(stk[j], stk[i], stk[i + 1]) <= + area(stk[j + 1], stk[i], stk[i + 1])) + j = nxt(j); + res = max(res, max(len2(stk[j] - stk[i]), len2(stk[j] - stk[i + 1]))); + } + printf("%d", res); + return 0; +} \ No newline at end of file diff --git a/省选准备/省选基础算法.pdf b/省选准备/省选基础算法.pdf index 0b70e1e..8fca381 100644 Binary files a/省选准备/省选基础算法.pdf and b/省选准备/省选基础算法.pdf differ diff --git a/省选准备/省选基础算法.tex b/省选准备/省选基础算法.tex index 3bd84f3..0f7f800 100644 --- a/省选准备/省选基础算法.tex +++ b/省选准备/省选基础算法.tex @@ -476,4 +476,9 @@ Manacher 模板题 \paragraph{练习题} \subparagraph{\href{http://poj.org/problem?id=3348}{POJ3348} - Cows} 模板题,注意公式要背对 \codeinput[Cows]{assets/day5/POJ3348.cpp} +\subsection{旋转卡壳} 你知道吗?旋转卡壳有16种读法。\\ + 首先有个很直观的结论:最远点对的两点一定在凸包上。我们的思路就是枚举凸包上的所有边,对每一条边找出凸包上离该边最远的顶点,计算这个顶点到该边两个端点的距离,并记录最大的值。当我们逆时针枚举边的时候,最远点的变化也是逆时针的,这样就可以不用从头计算最远点,而可以紧接着上一次的最远点继续计算,于是我们得到了$O(n)$的算法。 +\paragraph{练习题} +\subparagraph{\href{http://poj.org/problem?id=2187}{POJ2187} - Beauty Contest} 模板题,注意符号要写对 +\codeinput[Beauty Contest]{assets/day5/POJ2187.cpp} \end{document} \ No newline at end of file