Cod sursa(job #1758964)

Utilizator AlexNiuclaeNiculae Alexandru Vlad AlexNiuclae Data 18 septembrie 2016 11:41:57
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.73 kb
#include <bits/stdc++.h>

#define last_bit(x) (x&(-x))

using namespace std;

const int lgmax = 17;
const int nmax = 1e5 + 10;

const long long inf = 1e9;

int n, m, cnt;
int first[nmax], last[nmax], level[nmax];
long long aib[nmax], dp[nmax];

vector < int > g[nmax];
vector < pair < pair < int , int > , int > > v[nmax];

int N;
int rmq[lgmax+1][nmax<<1], Log[nmax<<1], whr[nmax];

void euler(int node, int dad, int lvl)
{
    level[node] = lvl;

    rmq[0][++N] = node;
    whr[node] = N;

    first[node] = ++cnt;

    for (auto &it : g[node])
    {
        if (it == dad) continue;

        euler(it, node, lvl + 1);
        rmq[0][++N] = node;
    }

    last[node] = cnt;
}

int lowest(int x , int y)
{
    return (level[x] <= level[y]) ? x : y;
}

void run_rmq()
{
    int i, j;
    for (i = 2; i <= N; ++i) Log[i] = Log[i>>1] + 1;

    for (i = 1; i <= Log[N]; ++i)
    {
        int prev_p2 = (1 << (i - 1));
        for (j = 1; j <= N - (1 << i) + 1; ++j)
            rmq[i][j] = lowest(rmq[i-1][j], rmq[i-1][j+(1<<(i-1))]);
    }
}

int get_lca(int x , int y)
{
    x = whr[x]; y = whr[y];
    if (x > y) swap(x , y);

    int k = Log[y - x + 1];

    return lowest(rmq[k][x], rmq[k][y-(1<<k)+1]);
}

void update(int i , long long x)
{
    for ( ; i <= n; i += last_bit(i))
        aib[i] += x;
}

long long query(int i)
{
    int ret = 0;
    for ( ; i ; i -= last_bit(i))
        ret += aib[i];
    return ret;
}

void dfs (int node)
{
    long long sum = 0;

    for (auto &it : g[node])
    {
        if (level[it] < level[node])
            continue;

        dfs(it);
        sum += dp[it];
    }

    dp[node] = inf;
    for (auto &it : v[node])
    {
        int x = it.first.first; int y = it.first.second;
        int cost = it.second;

        dp[node] = min(dp[node] , cost + query(first[x]) + query(first[y]) + sum);
    }

    update(first[node] , sum - dp[node]);
    update(last[node] + 1 , -sum + dp[node]);
}

void read_and_solve()
{
    scanf("%d %d", &n, &m);

    for (int i = 2; i <= n; ++i)
    {
        int x , y;
        scanf("%d", &x);

        g[x].push_back(i);
        g[i].push_back(x);
    }

    euler(1 , 0 , 1);
    run_rmq();

    for (int i = 1; i <= m; ++i)
    {
        int cost , x , y;
        scanf("%d %d", &x, &y);

        int node = get_lca(x , y);
        printf("%d\n", node);
    }

    //dfs(1);
}

void print_answer()
{
    printf("%lld\n", dp[1]);
}

int main()
{
    //freopen("paznici3.in","r",stdin);
    //freopen("paznici3.out","w",stdout);

    freopen("lca.in","r",stdin);
    freopen("lca.out","w",stdout);

    read_and_solve();
    //print_answer();

    return 0;
}