题意: 二维空间上有集合S,S中有n个点,将x轴上(0,0)到(X,0)分成多个部分,对于每一个部分中的所有点,离S中的最近的点是相同。
注意到任意两个点的连线的中垂线都可以将一个平面分成两个半平面,每个半平面到各自的点是最近的。那么可以维护一个堆栈,对于堆栈中的n个点已经将x轴分成了n+1个部分,那么新加入的点如果不影响栈顶的点,那么也不会影响栈内的其他点,因为现在需要分割的平面是属于栈顶的点的。如果影响栈顶的点,那么pop掉,直至不影响为止。
代码:
#include<bits/stdc++.h>
using namespace std;
const double eps = 1e-10;
const double PI = acos(-1.0);
struct Point { double x, y; Point(double x=0, double y=0):x(x),y(y) {} };
struct idPoint { Point p; int id; };
struct Circle { Point c; double r; Circle(Point c=Point(0, 0), double r = 0):c(c),r(r) {} };
typedef Point Vector;
int dcmp(double x) { if(fabs(x) < eps) return 0; else return x<0?-1:1; }
bool operator < (const Point& a, const Point& b) { return a.x<b.x || (a.x==b.x&&a.y<b.y); }
bool operator < (const idPoint& a, const idPoint& b) { return a.p < b.p; }
bool operator == (const Point& a, const Point& b) { return dcmp(a.x-b.x)==0 && dcmp(a.y-b.y)==0; }
Vector operator + (Vector A, Vector B) { return Vector(A.x+B.x, A.y+B.y); }
Vector operator - (Point A, Point B) { return Vector(A.x-B.x, A.y-B.y); }
Vector operator * (Vector A, double p) { return Vector(A.x*p, A.y*p); }
Vector operator / (Vector A, double p) { return Vector(A.x/p, A.y/p); }
double Dot(Vector A, Vector B) { return A.x*B.x + A.y*B.y; }
double Length(Vector A) { return sqrt(Dot(A, A)); }
double Angle(Vector A, Vector B) { return acos(Dot(A, B)/Length(A)/Length(B)); }
double Cross(Vector A, Vector B) { return A.x*B.y - A.y*B.x; }
Vector Rotate(Vector A, double rad) {
return Vector(A.x*cos(rad)-A.y*sin(rad), A.x*sin(rad)+A.y*cos(rad));
}//向量逆时针旋转
Point GetLineIntersection(Point P, Vector v, Point Q, Vector w) {
Vector u = P-Q;
double t = Cross(w, u)/Cross(v, w);
return P+v*t;
}//求直线交点
const int N = 1e5+5;
double ans[N];
Point lp[N];
idPoint p[N];
stack<int> S;
double solve(int u, int v) {
Point pp = (p[u].p+p[v].p)/2;
return GetLineIntersection({0,0}, {1,0}, pp, Rotate(p[v].p-pp, PI/2)).x;
}
int main() {
int n;
double X;
cin >> n >> X;
for(int i = 0; i < n; i++) {
scanf("%lf%lf", &p[i].p.x, &p[i].p.y);
p[i].id = i;
}
sort(p, p+n);
for(int i = 0; i < n; i++) {
if(S.empty()) {
S.push(i);
lp[i].x = 0;
lp[i].y = X;
continue;
}
while(!S.empty()) {
int u = S.top();
double xx = solve(u, i);
if(xx < lp[u].x) S.pop();
else {
lp[u].y = xx;
lp[i].x = xx;
lp[i].y = X;
break;
}
}
S.push(i);
}
memset(ans, 0, sizeof(ans));
while(!S.empty()) {
int u = S.top();
S.pop();
ans[p[u].id] = max(0.0, min(X, lp[u].y)-lp[u].x);
}
for(int i = 0; i < n; i++) printf("%.12f\n", ans[i]);
return 0;
}