Description
要求支持两个操作:
- 0 x y加入一个圆心为(x,y)的过原点的圆。
- 1 x y询问点(x,y)是否在所有圆内部。
强制在线。
Solution
二进制分组都不会啊
一个点(x0,y0)合法就等价于
(x0−xi)2+(y0−yi)2≤x2i+y2i
化简得到了y≥−x0y0x+x202y0+y02
这就是一次函数的形式。 就相当于是所有点都要在这条直线的上方。
在凸包上用这条直线逼近,直到有焦点,再判断一下截距的大小就好了。
实现的话,就是二分凸包上的斜率。
这道题要求强制在线。
二进制分组!
#include <bits/stdc++.h>
using namespace std;
const int N = 510010;
const int M = 30;
const double eps = 1e-8;
struct Point {
double x, y;
Point (double _x = 0, double _y = 0):x(_x), y(_y) {}
inline friend Point operator -(const Point &a, const Point &b) {
return Point(a.x - b.x, a.y - b.y);
}
inline friend double operator *(const Point &a, const Point &b) {
return a.x * b.y - b.x * a.y;
}
inline friend double operator /(const Point &a, const Point &b) {
return (a.y - b.y) / (a.x - b.x);
}
inline friend bool operator <(const Point &a, const Point &b) {
return a.x == b.x ? a.y < b.y : a.x < b.x;
}
};
Point In;
int n, opt, lim, cnt, online;
double x, y;
Point sta[N];
struct Group {
vector<Point> a, b;
int lim, size, usd;
inline void ConvexHull(void) {
b.clear(); size = 0; usd = 1;
sort(a.begin(), a.end());
sta[++size] = a[0];
for (int i = 1; i < lim; i++) {
while (size > 1 && (sta[size] - sta[size - 1]) * (a[i] - sta[size]) - eps < 0) --size;
sta[++size] = a[i];
}
for (int i = 1; i <= size; i++) b.push_back(sta[i]);
}
inline bool Query(double x0, double y0, double k) {
int L = 1, R = size - 1, Mid, Pos = 0;
while (L <= R) {
Mid = (L + R) >> 1;
if (k > b[Mid] / b[Mid - 1]) {
L = Mid + 1; Pos = Mid;
} else R = Mid - 1;
}
return x0 * x0 + y0 * y0 - 2.0 * x0 * b[Pos].x - 2.0 * y0 * b[Pos].y - eps < 0;
}
};
Group B[M];
inline void MakeGroup(Point &x, int pos) {
int cnt = 0; B[pos].a.clear();
B[pos].a.push_back(x);
for (int i = 1; i < pos; i++) {
B[i].usd = 0;
for (int j = 0; j < B[i].lim; j++)
B[pos].a.push_back(B[i].a[j]);
}
B[pos].usd = 1; B[pos].ConvexHull();
}
inline void Insert(Point &x) {
for (int i = 1; i <= lim; i++)
if (!B[i].usd) return MakeGroup(x, i);
}
inline bool Query(double x0, double y0) {
double k = -x0 / y0;
bool flag = (In.y != 0);
for (int i = 1; i <= lim; i++)
if (B[i].usd) flag &= B[i].Query(x0, y0, k);
return flag;
}
int main(void) {
freopen("1.in", "r", stdin);
scanf("%d", &n); lim = 25;
for (int i = 1; i <= lim; i++)
B[i].lim = 1 << (i - 1);
for (int i = 1; i <= n; i++) {
scanf("%d%lf%lf", &opt, &x, &y);
x += online; y += online;
if (opt) {
if (Query(x, y)) {
puts("Yes"); online++;
} else puts("No");
} else {
Insert(In = Point(x, y));
}
}
return 0;
}