Cod sursa(job #1556334)

Utilizator andreiiiiPopa Andrei andreiiii Data 24 decembrie 2015 16:59:34
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4 kb
#include <algorithm>
#include <fstream>
using namespace std;

const int NMAX = 100005, INF = 2000000001;

vector<int> G[NMAX];
int values[NMAX];

vector<int> paths[NMAX];
vector<int> aint[NMAX];
int path[NMAX], cntPaths;
int nodePos[NMAX];
int tsize[NMAX];
int pathFather[NMAX], pathLevel[NMAX], pathSize[NMAX];

void dfs(int node, int prev) {
    tsize[node] = 1;
    int l = -1;
    for (int p: G[node]) {
        if (p == prev) continue;
        dfs(p, node);
        tsize[node] += tsize[p];
        if (l == -1 || tsize[p] > tsize[l]) {
            l = p;
        }
    }
    if (l == -1) {
        path[node] = cntPaths++;
    } else {
        path[node] = path[l];
    }
    pathSize[path[node]]++;
}

void dfs2(int node, int prev) {
    paths[path[node]][nodePos[node] = pathSize[path[node]]++] = node;
    for (int p: G[node]) {
        if (p == prev) continue;
        if (path[p] != path[node]) {
            pathFather[path[p]] = node;
            pathLevel[path[p]] = pathLevel[path[node]] + 1;
        }
        dfs2(p, node);
    }
}

void build(vector<int>& aint, vector<int>& nodes,
        int node, int left, int right) {
    if (left == right) {
        aint[node] = values[nodes[left]];
    } else {
        int mid = (left + right) / 2;
        build(aint, nodes, 2 * node + 1, left, mid);
        build(aint, nodes, 2 * node + 2, mid + 1, right);
        aint[node] = max(aint[2 * node + 1], aint[2 * node + 2]);
    }
}

void update(vector<int>& aint, int node, int left, int right,
        int pos, int val) {
    if (left == right) {
        aint[node] = val;
    } else {
        int mid = (left + right) / 2;
        if (pos <= mid) update(aint, 2 * node + 1, left, mid, pos, val);
        else update(aint, 2 * node + 2, mid + 1, right, pos, val);
        aint[node] = max(aint[2 * node + 1], aint[2 * node + 2]);
    }
}

int query(vector<int>& aint, int node, int left, int right, int lq, int rq) {
    if (lq <= left && right <= rq) {
        return aint[node];
    } else {
        int mid = (left + right) / 2;
        int ret = 0;
        if (lq <= mid) ret = query(aint, 2 * node + 1, left, mid, lq, rq);
        if (rq > mid)
            ret = max(ret, query(aint, 2 * node + 2, mid + 1, right, lq, rq));
        return ret;
    }
}

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

    int n, q;
    fin >> n >> q;

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

    for (int i = 1; i < n; ++i) {
        int x, y;
        fin >> x >> y;
        G[x].push_back(y);
        G[y].push_back(x);
    }
    dfs(1, 0);
    for (int i = 0; i < cntPaths; ++i) {
        paths[i] = vector<int>(pathSize[i]);
        pathSize[i] = 0;
    }
    dfs2(1, 0);

    for (int i = 0; i < cntPaths; ++i) {
        aint[i] = vector<int>(pathSize[i] * 4);
        build(aint[i], paths[i], 0, 0, pathSize[i] - 1);
    }

    while (q-- > 0) {
        int type;
        fin >> type;
        
        if (type == 0) {
            int node, val;
            fin >> node >> val;
            update(aint[path[node]], 0, 0, pathSize[path[node]] - 1,
                    nodePos[node], val);
        } else {
            int x, y;
            fin >> x >> y;
            int px = path[x], py = path[y];

            int ans = 0;
            while (px != py) {
                if (pathLevel[px] > pathLevel[py]) {
                    ans = max(ans, query(aint[px], 0, 0, pathSize[px] - 1,
                                0, nodePos[x]));
                    x = pathFather[px];
                    px = path[x];
                } else {
                    ans = max(ans, query(aint[py], 0, 0, pathSize[py] - 1,
                                0, nodePos[y]));
                    y = pathFather[py];
                    py = path[y];
                }
            }
            int pmin = min(nodePos[x], nodePos[y]);
            int pmax = max(nodePos[x], nodePos[y]);
            ans = max(ans, query(aint[px], 0, 0, pathSize[px] - 1, pmin, pmax));

            fout << ans << '\n';
        }
    }

    fin.close();
    fout.close();
}