Cod sursa(job #1723770)

Utilizator lflorin29Florin Laiu lflorin29 Data 1 iulie 2016 15:13:08
Problema Heavy Path Decomposition Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 2.77 kb
#include <bits/stdc++.h>

using namespace std;

const int MAXN = 1e5;

int n, m, v[1 + MAXN], link[1 + MAXN], sz[1 + MAXN], niv[1 + MAXN], poz[1 + MAXN], lant_tata[1 + MAXN];
vector<int>g[1 + MAXN], lant[1 + MAXN], aint[1 + MAXN];


void change(vector<int>&tree, int pos, int val, int st, int dr, int nod) {
    if(pos < st || pos > dr) return;
    if(st == dr) {
       tree[nod] = val; return;}

    int mij = (st + dr) / 2;
    change(tree, pos, val, st, mij, nod * 2), change(tree, pos, val, mij + 1, dr, nod * 2 + 1);
    tree[nod] = max(tree[nod * 2], tree[nod * 2 + 1]);
}

int query(vector<int>&tree, int x, int y, int st, int dr, int nod) {
    if(x > dr || st > y) return 0;
    if(st >= x && dr <= y) return tree[nod];
    int mij = (st + dr) / 2;
    return max(query(tree, x, y, st, mij, nod * 2), query(tree, x, y, mij + 1, dr, nod * 2 + 1));
}

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

void df(int nod, int tata) {
    int best = 0;
    niv[nod] = niv[tata] + 1;
    sz[nod] = 1;
    link[nod] = nod;
    for(auto fiu: g[nod])
    {
        if(fiu == tata) continue;
        df(fiu, nod);
        lant_tata[link[fiu]] = nod;
        sz[nod] += sz[fiu];
        if(sz[fiu] > sz[best]) best = fiu, link[nod] = link[fiu];
    }
    lant[link[nod]].push_back(nod);
}

void build()
{
    lant_tata[link[1]] = 0;
    for(int i = 1; i <= n; ++i)
    {
        reverse(lant[i].begin(), lant[i].end());
        aint[i].resize(lant[i].size() * 4 + 9);
        int act = 1;
        for(auto it : lant[i]) {
           poz[it] = act;
           change(aint[i], act, v[it], 1, lant[i].size(), 1);
           act++;
        }
    }
}

int query(int x, int y) {
    int ans = 0;
    while(1) {
        if(link[x] == link[y]) {
           if(niv[x] < niv[y]) swap(x, y);
           ans = max(ans, query(aint[link[x]], poz[y], poz[x], 1, lant[link[x]].size(), 1));
           break;
        }

        if(niv[lant_tata[link[x]]] < niv[lant_tata[link[y]]]) swap(x, y);
        ans = max(ans, query(aint[link[x]], 1, poz[x], 1, lant[link[x]].size(), 1));
        x = lant_tata[link[x]];
    }
    return ans;
}

void solve() {

    for(int step = 1, t, x, y; step <= m; ++step)
    {
        cin >> t >> x >> y;
        int chain = link[x];
        if(t == 0) v[x] = y, change(aint[chain], poz[x], y, 1, lant[chain].size(), 1);
        else
            cout << query(x, y) << '\n';
    }
}

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

    read();
    df(1, 0);
    build();
    solve();
    return 0;
}