Cod sursa(job #1784766)

Utilizator oldatlantianSerban Cercelescu oldatlantian Data 20 octombrie 2016 14:48:22
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.26 kb
#include <bits/stdc++.h>
using namespace std;

const int SPQR = 100005; // Ave Imperator, morituri te salutant!

int cbuff;

int lvl[SPQR], w[SPQR], lch[SPQR], far[SPQR], pos[SPQR], v[SPQR];
vector<int> g[SPQR], chn[SPQR], barn[SPQR], spom[SPQR];

void dfs(int u) {
    w[u] = 1;
    for(auto i: g[u]) if(!lvl[i]) {
        lvl[i] = lvl[u] + 1;
        far[i] = u;
        barn[u].push_back(i);

        dfs(i);
        w[u]+= w[i]; } }

void rupeti_lanturile(int u) {
    int maxw, maxi;

    chn[cbuff].push_back(u);
    pos[u] = chn[cbuff].size() - 1;
    lch[u] = cbuff;

    maxw = -1;

    for(auto i: barn[u]) {
        if(w[i] > maxw) {
            maxw = w[i];
            maxi = i; } }

    if(maxw > 0) rupeti_lanturile(maxi);

    for(auto i: barn[u]) if(i != maxi) {
        chn[++cbuff].push_back(0);
        rupeti_lanturile(i); } }

void make_pom(int cidx, int nod, int st, int dr) {
    if(st==dr) {
        spom[cidx][nod] = v[chn[cidx][st]];
        return; }

    int m = (st + dr) / 2;

    make_pom(cidx, 2 * nod, st, m);
    make_pom(cidx, 2 * nod + 1, m + 1, dr);

    spom[cidx][nod] = max(spom[cidx][2 * nod], spom[cidx][2 * nod + 1]); }

void traiasca_regele(void) {
    for(int i=1; i<=cbuff; ++i) {
        spom[i].resize(4 * chn[i].size() + 5);
        make_pom(i, 1, 1, chn[i].size() - 1); } }

int query(int cidx, int nod, int st, int dr, int x, int y) {
    if(x<=st && dr<=y) {
        return spom[cidx][nod]; }

    int r, m;

    m = (st + dr) / 2;
    r = 0;

    if(x<=m) r = max(r, query(cidx, 2 * nod, st, m, x, y));
    if(y>m)  r = max(r, query(cidx, 2 * nod + 1, m + 1, dr, x, y));

    return r; }

void update(int cidx, int nod, int st, int dr, int pos, int val) {
    if(st == dr) {
        v[st] = val;
        spom[cidx][nod] = val;
        return; }

    int m = (st + dr) / 2;

    if(pos <= m) update(cidx, 2 * nod, st, m, pos, val);
    else update(cidx, 2 * nod + 1, m + 1, dr, pos, val);

    spom[cidx][nod] = max(spom[cidx][2 * nod], spom[cidx][2 * nod + 1]); }

int get_max(int a, int b) {
    if(lch[a] == lch[b]) {
        if(pos[a] > pos[b])
            return query(lch[a], 1, 1, chn[lch[a]].size()-1, pos[b], pos[a]);
        else
            return query(lch[a], 1, 1, chn[lch[a]].size()-1, pos[a], pos[b]); }

    int lead_a, lead_b;

    lead_a = chn[lch[a]][1];
    lead_b = chn[lch[b]][1];

    if(lvl[lead_a] > lvl[lead_b])
        return max(query(lch[a], 1, 1, chn[lch[a]].size()-1, 1, pos[a]), get_max(far[lead_a], b));
    else
        return max(query(lch[b], 1, 1, chn[lch[b]].size()-1, 1, pos[b]), get_max(far[lead_b], a)); }

int main(void) {
    freopen("heavypath.in",  "r", stdin);
    freopen("heavypath.out", "w", stdout);
    int tip, n, m, x, y;

    scanf("%d%d", &n, &m);
    for(int i=1; i<=n; ++i) {
        scanf("%d", &v[i]); }
    for(int i=1; i<n; ++i) {
        scanf("%d%d", &x, &y);
        g[x].push_back(y);
        g[y].push_back(x); }

    chn[1].push_back(0);
    lvl[1] = 1;
    cbuff = 1;

    dfs(1);
    rupeti_lanturile(1);
    traiasca_regele();

    while(m--) {
        scanf("%d%d%d", &tip, &x, &y);
        switch(tip) {
        case 0: {
            update(lch[x], 1, 1, chn[lch[x]].size()-1, pos[x], y);
            break; }
        case 1: {
            printf("%d\n", get_max(x, y));
            break; } } }

    return 0; }