luogu P3291 [SCOI2016]妖怪
Posted ZlycerQan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu P3291 [SCOI2016]妖怪相关的知识,希望对你有一定的参考价值。
二次联通门 : luogu P3291 [SCOI2016]妖怪
/* luogu P3291 [SCOI2016]妖怪 凸包 我果然还是naive 看见这题就想二分 结果惨挂 做了凸包后就想三分 又挂了。。 完美落入了每个坑。。果然还是自己太菜 对于每个妖怪,其在(a,b)时的最大战力为过当前点斜率为(-b/a)的直线的截距之和 最大的战力就是最外面的那条直线 对n个点做一个上凸包 最大值一定在凸包的右上部分(自行脑补) 那么这些点的斜率都有着一个范围ki-1<ki<ki+1 那么战力就变为了一个双钩函数 讨论求最值即可 */ #include <algorithm> #include <iostream> #include <cstdio> #include <cmath> void read (long long &now) { register char word = getchar (); int temp = 0; for (now = 0; !isdigit (word); word = getchar ()) if (word == ‘-‘) temp = 1; for (; isdigit (word); now = now * 10 + word - ‘0‘, word = getchar ()); if (temp) now = -now; } #define INF 1e9 struct Point { long long x, y; Point (long long __x, long long __y) : x (__x), y (__y) {} Point () {} bool operator < (const Point &now) const { return this->x == now.x ? this->y < now.y : this->x < now.x; } Point operator - (const Point &now) const { return Point (this->x - now.x, this->y - now.y); } }; inline long long Cross (const Point &A, const Point &B) { return A.x * B.y - A.y * B.x; } #define Max 1000250 inline double Calculate (const Point &now, const double &k) { return k >= 0 ? INF : (double) now.x + now.y + - k * now.x - now.y / k; } inline double Get_point_k (const Point &now) { return -sqrt ((double) now.y / now.x); } inline double Get_line_k (const Point &A, const Point &B) { return (A.x ^ B.x) ? ((double)(A.y - B.y) / (double) (A.x - B.x)) : INF; } int Get_convex_Hull (Point *point, int N, Point *Stack) { std :: sort (point + 1, point + N + 1); register int top = 0; for (int i = 1; i <= N; ++ i) { for (; top > 1 && Cross (Stack[top] - Stack[top - 1], point[i] - Stack[top - 1]) >= 0; -- top); Stack[++ top] = point[i]; } return top; } Point yukari[Max], Stack[Max]; int main (int argc, char *argv[]) { register int i; int N; scanf ("%d", &N); for (i = 1; i <= N; ++ i) read (yukari[i].x), read (yukari[i].y); int M = Get_convex_Hull (yukari, N, Stack); if (M < 2) { printf ("%.4lf", Calculate (Stack[1], Get_point_k (Stack[1]))); return 0; } double k, _k, __k, Answer = INF; k = Get_point_k (Stack[1]); __k = Get_line_k (Stack[1], Stack[2]); if (k >= __k) Answer = std :: min (Answer, Calculate (Stack[1], k)); k = Get_point_k (Stack[M]); _k = Get_line_k (Stack[M - 1], Stack[M]); if (k <= _k) Answer = std :: min (Answer, Calculate (Stack[M], k)); Answer = std :: min (Answer, Calculate (Stack[M], _k)); for (i = 2; i < M; ++ i) { _k = Get_line_k (Stack[i - 1], Stack[i]); __k = Get_line_k (Stack[i], Stack[i + 1]); k = Get_point_k (Stack[i]); Answer = std :: min (Answer, Calculate (Stack[i], _k)); if (k <= _k && k >= __k) Answer = std :: min (Answer, Calculate (Stack[i], k)); } printf ("%.4lf", Answer); return 0; }
以上是关于luogu P3291 [SCOI2016]妖怪的主要内容,如果未能解决你的问题,请参考以下文章