Cod sursa(job #1182941)

Utilizator mihai995mihai995 mihai995 Data 8 mai 2014 01:10:58
Problema Heavy Path Decomposition Scor 80
Compilator cpp Status done
Runda Arhiva educationala Marime 2.83 kb
#include <fstream>
#include <vector>
using namespace std;

const int N = 1 + 1e5;

vector<int> tree[N];

int T[N], son[N], head[N], stramos[N], succesor[N], n;
int heavyDepth[N], depth[N];
int cost[N], jmpCost[N];
int stack[N], level[N];

inline int lsb(int x){
    return x & -x;
}

void mark(int x, int lvl, int D){
    stack[lvl] = x;
    level[x] = lvl;
    head[x] = stack[1];
    heavyDepth[x] = D;

    if (son[x])
        mark(son[x], lvl + 1, D);
    else
        for (int i = 1 ; i <= lvl ; i++){
            stramos[ stack[i] ] = stack[i - lsb(i)];
            succesor[ stack[i] ] = stack[i + lsb(i)];
        }

    for (auto it = tree[x].begin() ; it != tree[x].end() ; it++)
        if (son[x] != *it && *it != T[x]){
            stack[0] = x;
            mark(*it, 1, 1 + heavyDepth[x]);
        }
}

int dfs(int x, int father){
    int weight = 1, val, bestVal = -1;
    T[x] = father;
    depth[x] = 1 + depth[father];

    for (auto it = tree[x].begin() ; it != tree[x].end() ; it++)
        if ( *it != father ){
            weight += val = dfs(*it, x);

            if (bestVal < val){
                bestVal = val;
                son[x] = *it;
            }
        }

    return weight;
}

int pathQuery(int x, int y){ ///x trebuie sa fie mai jos ca y
    int ans = 0;
    while (x != y)
        if ( depth[y] <= depth[ stramos[x] ] ){
            ans = max(ans, jmpCost[x]);
            x = stramos[x];
        } else {
            ans = max(ans, cost[x]);
            x = T[x];
        }
    return ans;
}

void update(int x, int val){
    cost[x] = val;
    for (int i = x ; i ; i = succesor[i])
        jmpCost[i] = max( cost[i], pathQuery( T[i], stramos[i] ) );
}

void build(){
    dfs(1, 0);
    mark(1, 1, 1);

    for (int i = 1 ; i <= n ; i++)
        update(i, cost[i]);
}

int lca(int x, int y){
    while ( heavyDepth[x] < heavyDepth[y] )
        y = T[ head[y] ];
    while ( heavyDepth[y] < heavyDepth[x] )
        x = T[ head[x] ];

    while (head[x] != head[y]){
        x = T[ head[x] ];
        y = T[ head[y] ];
    }

    return depth[x] < depth[y] ? x : y;
}

int query(int x, int y){
    int L = lca(x, y);
    return max( max( pathQuery(x, L), pathQuery(y, L) ), cost[L] );
}

int main(){
    int nrQ, tip, x, y;

    ifstream in("heavypath.in");
    in >> n >> nrQ;

    for (int i = 1 ; i <= n ; i++)
        in >> cost[i];

    for (int i = 1 ; i < n ; i++){
        in >> x >> y;

        tree[x].push_back(y);
        tree[y].push_back(x);
    }

    build();

    ofstream out("heavypath.out");

    while (nrQ--){
        in >> tip >> x >> y;

        if (tip == 0)
            update(x, y);
        else
            out << query(x, y) << '\n';
    }

    in.close();
    out.close();

    return 0;
}