Cod sursa(job #2206880)

Utilizator Chirita_MateiChirita Matei Chirita_Matei Data 24 mai 2018 09:20:53
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.01 kb
#include <bits/stdc++.h>
 
using namespace std;
ofstream fout("heavypath.out");
//ifstream fin("heavypath.in");
 
const int NMax = 100010;
vector<int> G[NMax];
 
class Path {
public:
    vector<int> P;
    vector<int> T;
    int parent;
 
    Path() {
        P.clear();
        T.clear();
        parent = 0;
    }
 
    void update(int node, int st, int dr, int pos, int val) {
        if (st == dr) { T[node] = val; return; }
 
        int mid = (st + dr) / 2;
        if (pos <= mid) update(node * 2, st, mid, pos, val);
        else            update(node * 2 + 1, mid + 1, dr, pos, val);
 
        T[node] = max(T[node * 2], T[node * 2 + 1]);
    }
 
    int maxim(int node, int st, int dr, int ql, int qr) {
        if (st == ql && dr == qr) return T[node];
 
        int mid = (st + dr) / 2;
        int nr1 = 0, nr2 = 0;
 
        if (ql <= mid) nr1 = maxim(node * 2, st, mid, ql, min(qr, mid));
        if (qr > mid)  nr2 = maxim(node * 2 + 1, mid + 1, dr, max(ql, mid + 1), qr);
 
        return max(nr1, nr2);
    }
 
    void addToPath(int node) {
        P.push_back(node);
    }
};
 
class Node {
public:
    int niv;
    int sub;
    int pos;
    int val;
    int path;
};
 
vector<Path> paths;
vector<Node> nodes(NMax);
 
void makePaths(int node, int prev, int level) {
    int maxi = 0;
    int connect = 0;
    int subarb = 0;
 
    nodes[node].niv = level;
 
    for (int i = 0; i < G[node].size(); i++) {
        int next = G[node][i];
        if (next == prev) continue;
 
        makePaths(next, node, level + 1);
 
        if (nodes[next].sub > maxi) {
            maxi = nodes[next].sub;
            connect = next;
        }

	subarb += nodes[next].sub;
    }
 
    if (!maxi) {
        Path aux;
        aux.addToPath(node);
        paths.push_back(aux);
        nodes[node].path = paths.size() - 1;
        nodes[node].sub = 1;
        return;
    }
 
    paths[nodes[connect].path].addToPath(node);
    nodes[node].path = nodes[connect].path;
    nodes[node].sub = subarb + 1;
 
    for (int i = 0; i < G[node].size(); i++) {
        int next = G[node][i];
        if (next == prev) continue;
 
        if (next != connect) {
            paths[nodes[next].path].parent = node;
        }
    }
}
 
void reversePathsAndMakeTrees() {
    for (int i = 0; i < paths.size(); i++) {
        reverse(paths[i].P.begin(), paths[i].P.end());
 
        vector<int> aux = paths[i].P;
        paths[i].T.resize(4 * aux.size() + 1);
 
        for (int j = 0; j < aux.size(); j++) {
            paths[i].update(1, 1, aux.size(), j + 1, nodes[aux[j]].val);
            nodes[aux[j]].pos = j + 1;
        }
    }
}
 
void solve1(int node, int val) {
    nodes[node].val = val;
    paths[nodes[node].path].update(1, 1, paths[nodes[node].path].P.size(), nodes[node].pos, val);
}
 
int solve2(int x, int y) {
    if (nodes[paths[nodes[x].path].P[0]].niv < nodes[paths[nodes[y].path].P[0]].niv) swap(x, y);
 
    if (nodes[x].path == nodes[y].path) return paths[nodes[x].path].maxim(1, 1, paths[nodes[x].path].P.size(), min(nodes[x].pos, nodes[y].pos), max(nodes[x].pos, nodes[y].pos));
    else return max(paths[nodes[x].path].maxim(1, 1, paths[nodes[x].path].P.size(), 1, nodes[x].pos), solve2(paths[nodes[x].path].parent, y));
}
 
void query(int m) {
    int x, y, o;
    for (int i = 1; i <= m; i++) {
        //fin >> o >> x >> y;
 
        scanf("%d%d%d", &o, &x, &y);
        switch (o) {
        case 0: solve1(x, y); break;
        case 1: fout << solve2(x, y) << '\n'; break;
        }
    }
}
 
int main()
{
    int n, m, x, y;
 
    freopen("heavypath.in", "r", stdin);
    //fin >> n >> m;
    scanf("%d%d", &n, &m);
 
    for (int i = 1; i <= n; i++) scanf("%d", &nodes[i].val);
    for (int i = 1; i < n; i++) {
        //fin >> x >> y;
        scanf("%d%d", &x, &y);
 
        G[x].push_back(y);
        G[y].push_back(x);
    }
 
    makePaths(1, 0, 0);
    reversePathsAndMakeTrees();
    query(m);
 
 
    return 0;
}