Cod sursa(job #1959710)

Utilizator antanaAntonia Boca antana Data 9 aprilie 2017 20:21:13
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.75 kb
#include <bits/stdc++.h>

#define MAXN 100001

using namespace std;

vector <int> G[MAXN], P[MAXN], aint[MAXN];

int n, paths, weight[MAXN], path[MAXN], father[MAXN], depth[MAXN], pos[MAXN], dim[MAXN], value[MAXN];
int answer, position, val, l1, l2;

void build(int index, int node, int left, int right) {
    if(left == right) {
        aint[index][node] = value[P[index][left-1]];
        return;
    }

    int middle = (left + right)/2;
    build(index, node*2, left, middle);
    build(index, node*2+1, middle+1, right);

    aint[index][node] = max(aint[index][node*2], aint[index][node*2+1]);
}

void DFS(int node) {
    bool leaf = 1;
    int maxWeight = 0;

    weight[node] = 1;
    for(int son: G[node]) {
        if(son != father[node]) {
            leaf = 0;
            depth[son] = depth[node] + 1;
            father[son] = node;
            DFS(son);
            weight[node] += weight[son];
            if(weight[maxWeight] < weight[son])
                maxWeight = son;
        }
    }

    if(leaf) {
        paths++;
        P[paths].push_back(node);
        path[node] = paths;
        dim[paths] = 1;
        return;
    }

    P[path[maxWeight]].push_back(node);
    path[node] = path[maxWeight];
    dim[path[node]] ++;
}

void makePaths() {
    for(int i=1; i<=paths; ++i) {
        reverse(P[i].begin(), P[i].end());

        for(int j=0; j<dim[i]; ++j)
            pos[P[i][j]] = j+1;

        aint[i].push_back(0);
        for(int j=1; j<=4 * dim[i]; ++j)
            aint[i].push_back(0);

        build(i, 1, 1, dim[i]);
    }
}

void update(int index, int node, int left, int right) {
    if(left == right) {
        aint[index][node] = val;
        return;
    }

    int middle = (left + right)/2;

    if(position <= middle) update(index, node*2, left, middle);
    else update(index, node*2+1, middle+1, right);

    aint[index][node] = max(aint[index][node*2], aint[index][node*2+1]);
}

void query(int index, int node, int left, int right) {
    if(l1 <= left && right <= l2) {
        answer = max(answer, aint[index][node]);
        return;
    }

    int middle = (left + right)/2;

    if(l1 <= middle) query(index, node*2, left, middle);
    if(l2 > middle) query(index, node*2+1, middle+1, right);
}

int searchInTree(int node1, int node2) {
    int dad1, dad2, x, y;

    answer = 0;

    x = node1;
    y = node2;
    dad1 = P[path[node1]][0];
    dad2 = P[path[node2]][0];

    while(path[x] != path[y]) {
        if(depth[dad1] < depth[dad2])
            swap(x, y), swap(dad1, dad2);

        l1 = 1;
        l2 = pos[x];
        query(path[x], 1, 1, dim[path[x]]);

        x = father[dad1];

        dad1 = P[path[x]][0];
        dad2 = P[path[y]][0];
    }

    l1 = min(pos[x], pos[y]);
    l2 = max(pos[x], pos[y]);
    query(path[x], 1, 1, dim[path[x]]);

    return answer;
}

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

    int type, q, i, x, y;

    scanf("%d%d", &n, &q);
    for(i=1; i<=n; ++i)
        scanf("%d", &value[i]);

    for(i=1; i<n; ++i) {
        scanf("%d%d", &x, &y);
        G[x].push_back(y);
        G[y].push_back(x);
    }

    depth[1] = 1;
    DFS(1);
    makePaths();

    /*
    for(i=1; i<=paths; ++i) {
        printf("Pentru lantul %d: ", i);
        for(int j = 0; j<dim[i]; ++j)
            printf("%d ", P[i][j]);
        printf("\n");
    }*/

    while(q--) {
        scanf("%d%d%d", &type, &x, &y);
        if(type == 0) {
            position = pos[x];
            val = y;
            value[x] = y;
            update(path[x], 1, 1, dim[path[x]]);
        } else printf("%d\n", searchInTree(x, y));
    }

    return 0;
}