模板。
#include <bits/stdc++.h>
using namespace std;
#define N 100010
#define M 1000010
#define ULL unsigned long long
#define LL long long
#define ls (i << 1)
#define rs (ls | 1)
#define md ((ll + rr) >> 1)
#define lson ll, md, ls
#define rson md + 1, rr, rs
#define inf 0x3f3f3f3f
#define eps 1e-6
#define pii pair<int, int>
#define MP make_pair
#define mod 1000000007
#define sqr(x) ((x) * (x))
int dcmp(double x) {
if (fabs(x) < eps) return 0;
return x < 0 ? -1 : 1;
}
struct point {
double x, y;
int id;
struct Edge *e;
bool operator < (const point & p) const {
return dcmp(x - p.x) != 0 ? x < p.x : dcmp(y - p.y) < 0;
}
bool operator == (const point & p) const {
return dcmp(x - p.x) == 0 && dcmp(y - p.y) == 0;
}
void input(int i) {
id = i;
scanf("%lf%lf", &x, &y);
}
}p[N];
double cross(point & o, point & a, point & b) {
return (a.x - o.x) * (b.y - o.y) - (b.x - o.x) * (a.y - o.y);
}
double dot(point & o, point & a, point & b) {
return (a.x - o.x) * (b.x - o.x) + (a.y - o.y) * (b.y - o.y);
}
double dis(point a, point b) {
return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
struct Edge {
point *o, *d;
Edge *on, *op, *dn, *dp;
};
#define Op(e,p) ((e)->o==p?(e)->d:(e)->o)
#define Next(e,p) ((e)->o==p?(e)->on:(e)->dn)
#define Prev(e,p) ((e)->o==p?(e)->op:(e)->dp)
struct Delaunay {
void solve(point * ps, int n) { //点集需要 sort 和 unique
sort(ps, ps + n);
edge_num = 0;
rubb = NULL;
for (int i = 0; i < n; i++) ps[i].e = NULL;
Edge* l_cw, *r_ccw;
divide(ps, 0, n, l_cw, r_ccw);
}
Edge es[M], *rubb;
int edge_num;
Edge *make_edge(point &u, point &v) {
Edge * e;
if (rubb == NULL) {
e = es + edge_num++;
}
else {
e = rubb;
rubb = rubb->dn;
}
e->on = e->op = e->dn = e->dp = e;
e->o = &u; e->d = &v;
if (u.e == NULL) u.e = e;
if (v.e == NULL) v.e = e;
return e;
}
void delete_edge(Edge *e) {
point *u = e->o, *v = e->d;
if (u->e == e) u->e = e->on;
if (v->e == e) v->e = e->dn;
Prev(e->on, u) = e->op;
Next(e->op, u) = e->on;
Prev(e->dn, v) = e->dp;
Next(e->dp, v) = e->dn;
e->dn = rubb;
rubb = e;
}
void splice(Edge *a, Edge *b, point *v) {
Edge *n;
n = Next(a, v); Next(a, v) = b;
Prev(n, v) = b;
Next(b, v) = n; Prev(b, v) = a;
}
Edge *join(Edge *a, point *u, Edge *b, point *v, int s) {
Edge *e = make_edge(*u, *v);
if (s == 0) {
splice(Prev(a, u), e, u);
splice(b, e, v);
}
else {
splice(a, e, u);
splice(Prev(b, v), e, v);
}
return e;
}
void lower_tangent(Edge * & l, Edge * & r, point * & s, point * & u) {
point *dl = Op(l, s), *dr = Op(r, u);
while (1) {
if (dcmp(cross((*s), (*dl), (*u))) > 0) {
l = Prev(l, dl); s = dl; dl = Op(l, s);
}
else if (dcmp(cross((*u), (*dr), (*s))) < 0) {
r = Next(r, dr); u = dr; dr = Op(r, u);
}
else break;
}
}
void merge(Edge *r_cw_l, point *s, Edge *l_ccw_r, point *u, Edge
**l_tangent) {
Edge *b, *lc, *rc;
point *dlc, *drc;
double crc, clc;
lower_tangent(r_cw_l, l_ccw_r, s, u);
b = join(r_cw_l, s, l_ccw_r, u, 1);
*l_tangent = b;
do {
lc = Next(b, s); rc = Prev(b, u); dlc = Op(lc, s); drc = Op(rc, u);
double cplc = cross(*dlc, *s, *u);
double cprc = cross(*drc, *s, *u);
bool alc = dcmp(cplc)>0, arc = dcmp(cprc)>0;
if (!alc && !arc) break;
if (alc) {
clc = dot(*dlc, *s, *u) / cplc;
do {
Edge * next = Next(lc, s);
point & dest = *Op(next, s);
double cpn = cross(dest, *s, *u);
if (dcmp(cpn) <= 0) break;
double cn = dot(dest, *s, *u) / cpn;
if (dcmp(cn - clc)>0) break;
delete_edge(lc);
lc = next;
clc = cn;
} while (1);
}
if (arc) {
crc = (double)dot(*drc, *s, *u) / cprc;
do {
Edge * prev = Prev(rc, u);
point & dest = *Op(prev, u);
double cpp = cross(dest, *s, *u);
if (dcmp(cpp) <= 0) break;
double cp = dot(dest, *s, *u) / cpp;
if (dcmp(cp - crc) > 0) break;
delete_edge(rc);
rc = prev;
crc = cp;
} while (1);
}
dlc = Op(lc, s); drc = Op(rc, u);
if (!alc || (alc && arc && dcmp(crc - clc) < 0)) {
b = join(b, s, rc, drc, 1);
u = drc;
}
else {
b = join(lc, dlc, b, u, 1);
s = dlc;
}
} while (1);
}
void divide(point *p, int l, int r, Edge * & l_ccw, Edge * & r_cw) {
int n = r - l;
Edge *l_ccw_l, *r_cw_l, *l_ccw_r, *r_cw_r, *l_tangent, *c;
if (n == 2) {
l_ccw = r_cw = make_edge(p[l], p[l + 1]);
}
else if (n == 3) {
Edge * a = make_edge(p[l], p[l + 1]), *b = make_edge(p[l + 1], p[l + 2]);
splice(a, b, &p[l + 1]);
double c_p = cross(p[l], p[l + 1], p[l + 2]);
if (dcmp(c_p)>0) {
c = join(a, &p[l], b, &p[l + 2], 1); l_ccw = a; r_cw = b;
}
else if (dcmp(c_p) < 0) {
c = join(a, &p[l], b, &p[l + 2], 0); l_ccw = c; r_cw = c;
}
else {
l_ccw = a; r_cw = b;
}
}
else if (n > 3) {
int split = (l + r) / 2;
divide(p, l, split, l_ccw_l, r_cw_l);
divide(p, split, r, l_ccw_r, r_cw_r);
merge(r_cw_l, &p[split - 1], l_ccw_r, &p[split], &l_tangent);
if (l_tangent->o == &p[l]) l_ccw_l = l_tangent;
if (l_tangent->d == &p[r - 1]) r_cw_r = l_tangent;
l_ccw = l_ccw_l; r_cw = r_cw_r;
}
}
} de;
struct tree_edge {
int u, v;
double c;
tree_edge(int u = 0, int v = 0, double c = 0) : u(u), v(v), c(c) {}
bool operator < (const tree_edge &b) const {
return c < b.c;
}
}tree_e[M];
void addEdge(int &k, int u, int v, double d) {
tree_e[++k] = tree_edge(u, v, d);
}
void getEdge(int &k, int n) {
k = 0;
Edge *st, *cur;
point *u, *v;
for (int i = 0; i < n; ++i) {
u = &pnt[i];
st = cur = u->e;
do {
v = Op(cur, u);
if (u < v)
addEdge(k, u->id, v->id, dis(*u, *v));
} while ((cur = Next(cur, u)) != st);
}
}
void enum_triangle(point *ps, int n) {
Edge *e_start, *e, *nxt;
point *u, *v, *w;
for (int i = 0; i < n; i++) {
u = &ps[i];
e_start = e = u->e;
do {
v = Op(e, u);
if (u < v) {
nxt = Next(e, u);
w = Op(nxt, u);
if (u < w && Next(nxt, w) == Prev(e, v)) {
// now, (u v w) is a triangle!!!!!!
// 这时,uvw 的外接圆是空的(不包含 ps 中的其他点),如果要求最大空圆,则计算 uvw 的外接圆就可以!
}
}
} while ((e = Next(e, u)) != e_start);
}
}
int n, fa[N];
struct LCA{
int fst[N], vv[M], nxt[M], dep[N], e;
double cost[M], fee[N][22];
int fa[N][22];
void init(){
memset(fst, -1, sizeof fst); e = 0;
}
void add(int u, int v, double c){
vv[e] = v, nxt[e] = fst[u], cost[e] = c, fst[u] = e++;
}
void dfs(int u, int p, int d, double c){
fa[u][0] = p, dep[u] = d, fee[u][0] = c;
for(int i = fst[u]; ~i; i = nxt[i]){
int v = vv[i];
if(v == p) continue;
dfs(v, u, d + 1, cost[i]);
}
}
void init_lca(){
for(int k = 0; k < 21; ++k)
for(int i = 1; i <= n; ++i){
if(fa[i][k] == -1)
fa[i][k+1] = -1, fee[i][k+1] = fa[i][k];
else
fa[i][k+1] = fa[fa[i][k]][k],
fee[i][k+1] = max(fee[i][k], fee[fa[i][k]][k]);
}
}
double lca(int u, int v){
double ret = 0;
if(dep[u] > dep[v]) swap(u, v);
for(int i = 0; i < 21; ++i)
if((dep[v] - dep[u]) >> i & 1){
ret = max(ret, fee[v][i]);
v = fa[v][i];
}
if(v == u) return ret;
for(int i = 21; i >= 0; --i)
if(fa[u][i] != fa[v][i]){
ret = max(ret, fee[u][i]);
ret = max(ret, fee[v][i]);
u = fa[u][i], v = fa[v][i];
}
ret = max(ret, fee[u][0]);
ret = max(ret, fee[v][0]);
return ret;
}
}go;
int find(int u){
if(fa[u] != u) fa[u] = find(fa[u]);
return fa[u];
}
int main() {
do{
scanf("%d", &n);
for (int i = 0; i < n; ++i) {
scanf("%lf%lf", &pnt[i].x, &pnt[i].y);
pnt[i].id = i + 1;
}
de.solve(pnt, n);
int k = 0;
getEdge(k, n);
sort(tree_e + 1, tree_e + 1 + k);
for(int i = 0; i <= n; ++i) fa[i] = i;
double ans = 0;
go.init();
for (int i = 1; i <= k; ++i){
int u = tree_e[i].u, v = tree_e[i].v;
double c = tree_e[i].c;
int fu = find(u), fv = find(v);
if(fu == fv) continue;
fa[fu] = fv;
go.add(u, v, c);
go.add(v, u, c);
ans += c;
}
go.dfs(1, -1, 0, 0);
go.init_lca();
int m;
scanf("%d", &m);
while(m--){
int u, v;
scanf("%d%d", &u, &v);
printf("%.6f\n", go.lca(u, v));
}
}while(0);
return 0;
}