Cod sursa(job #2306791)

Utilizator caesar2001Stoica Alexandru caesar2001 Data 22 decembrie 2018 21:18:23
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.5 kb
#include <iostream>
#include <fstream>
#include <algorithm>
#include <vector>
#include <cmath>

using namespace std;

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

const int NMAX = 100005;

vector<int> g[NMAX], p[NMAX];
int color[NMAX], ncolors, father[NMAX], ind[NMAX];
int v[NMAX], h[NMAX], dad[NMAX];
bool visited[NMAX];

int dfs(int node, int level) {
    h[node] = level;

    int dim = 1, mx = 0, currcolor;
    for(auto it : g[node]) {
        if(!visited[it]) {
            visited[it] = 1;
            dad[it] = node;
            int aux = dfs(it, level + 1);
            dim += aux;

            if(aux > mx) {
                mx = aux;
                currcolor = color[it];
            }
        }
    }
    if(dim == 1) {
        ncolors ++;
        color[node] = ncolors;
        ind[node] = 1;
        p[ncolors].push_back(node);
        father[ncolors] = node;
    } else {
        color[node] = currcolor;
        ind[node] = p[currcolor].size() + 1;
        p[currcolor].push_back(node);
        father[currcolor] = node;
    }

    return dim;
}

vector<int> aint[NMAX];

void build(int c, int node, int le, int ri) {
    if(le == ri) {
        aint[c][node] = v[p[c][le - 1]];
        return;
    }

    int mid = (le + ri) / 2;
    build(c, node * 2, le, mid);
    build(c, node * 2 + 1, mid + 1, ri);

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

void update(int c, int val, int pos, int node, int le, int ri) {
    if(le == ri) {
        aint[c][node] = val;
        return;
    }

    int mid = (le + ri) / 2;
    if(pos <= mid)
        update(c, val, pos, node * 2, le, mid);
    else
        update(c, val, pos, node * 2 + 1, mid + 1, ri);

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

int query(int c, int from, int to, int node, int le, int ri) {
    if(from <= le && ri <= to)
        return aint[c][node];

    int mid = (le + ri) / 2;
    int ans = 0;
    if(from <= mid)
        ans = query(c, from, to, node * 2, le, mid);
    if(mid < to)
        ans = max(ans, query(c, from, to, node * 2 + 1, mid + 1, ri));
    return ans;
}

int main() {
    int n, m;
    in >> n >> m;
    for(int i = 1; i <= n; i ++)
        in >> v[i];
    for(int i = 1; i < n; i ++) {
        int x, y;
        in >> x >> y;
        g[x].push_back(y);
        g[y].push_back(x);
    }

    visited[1] = 1;
    dfs(1, 1);

    for(int i = 1; i <= ncolors; i ++) {
        aint[i].resize(4 * (p[i].size()) + 1);
        build(i, 1, 1, p[i].size());
    }

    for(int qry = 1; qry <= m; qry ++) {
        int t, x, y;
        in >> t >> x >> y;

        if(t == 0)
            update(color[x], y, ind[x], 1, 1, p[color[x]].size());
        if(t == 1) {
            int ans = 0;
            while(color[x] != color[y]) {
                if(h[father[color[x]]] > h[father[color[y]]]) {
                    ans = max(ans, query(color[x], ind[x], ind[father[color[x]]], 1, 1, p[color[x]].size()));
                    x = dad[father[color[x]]];
                } else {
                    ans = max(ans, query(color[y], ind[y], ind[father[color[y]]], 1, 1, p[color[y]].size()));
                    y = dad[father[color[y]]];
                }
            }

            if(h[x] < h[y])
                swap(x, y);

            ans = max(ans, query(color[x], ind[x], ind[y], 1, 1, p[color[x]].size()));
            out << ans << "\n";
        }
    }

    return 0;
}