Codeforces Round #238 (Div. 1) D題(倍增lca)
阿新 • • 發佈:2019-02-10
#include
#include
#include
using namespace std;
const int N = 100000+5;
struct Edge {
int v, next;
}edge[N<<1];
int st[N], nxt[N];
double x[N], y[N];
int p[N][21], dep[N], head[N], E;
void newedge(int u, int v) {
edge[E].v = v; edge[E].next = head[u];
head[u] = E++;
}
void init() {
memset(head, -1, sizeof(head));
E = 0;
}
double cal(int i, int j) {
return (y[j] - y[i])/(x[j]-x[i]);
}
void dfs(int u, int fa) {
if(fa == -1)
dep[u] = 0;
else {
dep[u] = dep[fa]+1;
p[u][0] = fa;
for(int i = 1;i < 20; i++) p[u][i] = p[p[u][i-1]][i-1];
}
for(int i = head[u];i != -1;i = edge[i].next) {
int v = edge[i].v;
if(v != fa) dfs(v, u);
}
}
int lca(int a, int b) {
if(dep[a] > dep[b]) swap(a, b);
if(dep[a] < dep[b]) {
int cur = dep[b] - dep[a];
for(int i = 0;i < 20; i++) if(cur & (1<= 0; i--) if(p[a][i] != p[b][i])
a = p[a][i], b = p[b][i];
a = p[a][0]; b = p[b][0];
}
return a;
}
int main() {
init();
int n;
scanf("%d", &n);
for(int i = 1;i <= n; i++) scanf("%lf%lf", &x[i], &y[i]);
int top = 0;
for(int i = n;i >= 1; i--) {
while(top >= 2 && cal(i, st[top]) < cal(st[top], st[top-1]))
top--;
if(top) nxt[i] = st[top];
else nxt[i] = i;
st[++top] = i;
}
for(int i = 1;i < n; i++) {
newedge(i, nxt[i]);
newedge(nxt[i], i);
}
dfs(n, -1);
int m, u, v;
scanf("%d", &m);
while(m--) {
scanf("%d%d", &u, &v);
printf("%d ", lca(u, v));
}
puts("");
return 0;
}