Cod sursa(job #1679757)

Utilizator TarabanDragosTaraban Dragos-Petru TarabanDragos Data 8 aprilie 2016 10:55:25
Problema Ciclu Eulerian Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 4.27 kb
#include <fstream>
#include <algorithm>
#include <vector>
#include <cstring>

using namespace std;

ifstream fin("heavypath.in");
ofstream fout("heavypath.out");

const int dim = 100005;

int n, opCount;

int v[dim], level[dim], parent[dim], subTree[dim], start[dim];

vector<int> tree[dim];

int pathCount, inPath[dim], parentPath[dim], posInPath[dim];
vector<int> paths[dim];

void dfs(int node, int lvl, int prt) {

    level[node] = lvl;
    subTree[node] = 1;
    parent[node] = prt;

    int maxSubTree = 0, maxSon = 0;
    for (vector<int>::iterator son = tree[node].begin(); son != tree[node].end(); ++son) {

        if (level[*son])
            continue;

        dfs(*son, lvl + 1, node);
        subTree[node] += subTree[*son];

        if (subTree[*son] > maxSubTree) {
            maxSubTree = subTree[*son];
            maxSon = *son;
        }

    }

    if (maxSubTree == 0) {

        paths[++pathCount].push_back(node);
        inPath[node] = pathCount;
        parentPath[pathCount] = parent[node];

    }
    else {

        paths[inPath[maxSon]].push_back(node);
        inPath[node] = inPath[maxSon];
        parentPath[inPath[node]] = parent[node];

    }

}

int aint[4 * dim];

void update(int node, int left, int right, int pos, int val, int decal) {

    if (left > right)
        return;

    if (left == right && left == pos) {

        aint[node + decal] = val;
        return;

    }

    int mid = (left + right) / 2;

    if (pos <= mid)
        update(2 * node, left, mid, pos, val, decal);
    else
        update(2 * node + 1, mid + 1, right, pos, val, decal);

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

}

int query(int node, int left, int right, int qLeft, int qRight, int decal) {

    if (qLeft <= left && right <= qRight)
        return aint[node + decal];

    int mid = (left + right) / 2, retLeft = 0, retRight = 0;

    if (qLeft <= mid)
        retLeft = query(2 * node, left, mid, qLeft, qRight, decal);
    if (mid < qRight)
        retRight = query(2 * node + 1, mid + 1, right, qLeft, qRight, decal);

    return max(retLeft, retRight);

}

int main() {

    fin >> n >> opCount;

    for (int i = 1; i <= n; ++i)
        fin >> v[i];

    for (int i = 1; i < n; ++i) {

        int x, y;
        fin >> x >> y;

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

    }

    dfs(1, 1, 0);

    for (int i = 1; i <= pathCount; ++i) {

        start[i] = start[i - 1] + 4 * paths[i - 1].size();

        int j = 0, k = paths[i].size() - 1;
        for (; j < k; ++j, --k) {

            swap(paths[i][j], paths[i][k]);
            posInPath[paths[i][j]] = j;
            posInPath[paths[i][k]] = k;

        }

        posInPath[paths[i][j]] = j;

    }

    for (int i = 1; i <= n; ++i) {

        update(1, 0, paths[inPath[i]].size() - 1, posInPath[i], v[i], start[inPath[i]]);

    }

    while (opCount--) {

        int op;
        fin >> op;

        if (op == 0) {

            int node, val;
            fin >> node >> val;

            update(1, 0, paths[inPath[node]].size() - 1, posInPath[node], val, start[inPath[node]]);
            continue;

        }

        int x, y;
        fin >> x >> y;

        int sol = 0;

        while (true) {

            int path1 = inPath[x];
            int path2 = inPath[y];

            if (path1 == path2) {

                int a = posInPath[x];
                int b = posInPath[y];
                if (a > b) swap(a, b);

                sol = max(sol, query(1, 0, paths[path1].size() - 1, a, b, start[path1]));
                break;

            }
            else if (level[parentPath[path1]] > level[parentPath[path2]]) {

                int a = posInPath[x];
                sol = max(sol, query(1, 0, paths[path1].size() - 1, 0, a, start[path1]));

                x = parentPath[path1];

            }
            else {

                int a = posInPath[y];
                sol = max(sol, query(1, 0, paths[path2].size() - 1, 0, a, start[path2]));

                y = parentPath[path2];

            }

        }

        fout << sol << '\n';

    }

    return 0;

}

//Trust me, I'm the Doctor!