1. 程式人生 > >Codeforces Round #238 (Div. 1) D題(倍增lca)

Codeforces Round #238 (Div. 1) D題(倍增lca)

#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;
}