Cod sursa(job #2037959)

Utilizator cristina_borzaCristina Borza cristina_borza Data 12 octombrie 2017 23:46:04
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.15 kb
#include <bits/stdc++.h>

using namespace std;

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

const int Dim = 1e5 + 5;

int w[ Dim ], v[ Dim ], nivel[ Dim ], aint[5 * Dim], l[ Dim ], DimLant[ Dim ], NivLant[ Dim ], TataLant[ Dim ], Dec[ Dim ];
int n, m, type, x, y, NrLanturi;

vector <int> P[ Dim ], G[ Dim ];

void build_tree (int inc, int sf, int node, int dec, int lant) {
    if (inc == sf) {
        aint[node + dec] = v[P[ lant ][inc - 1]];
        return;
    }

    int mid = (inc + sf) / 2;

    build_tree (inc, mid, 2 * node, dec, lant);
    build_tree (mid + 1, sf, 2 * node + 1, dec, lant);

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

void update_tree (int inc, int sf, int pos, int val, int node, int dec) {
    if (inc == sf) {
        aint[node + dec] = val;
        return;
    }

    int mid = (inc + sf) / 2;

    if (pos <= mid)
        update_tree (inc, mid, pos, val, 2 * node, dec);
    else
        update_tree (mid + 1, sf, pos, val, 2 * node + 1, dec);

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

int query_tree (int inc, int sf, int a, int b, int node, int dec) {
    if (inc > sf || a > sf || b < inc) {
        return 0;
    }

    if (a <= inc && sf <= b)
        return aint[node + dec];

    int mid = (inc + sf) / 2;

    if (b <= mid) {
        return query_tree (inc, mid, a, b, 2 * node, dec);
    }

    if (a > mid) {
        return query_tree (mid + 1, sf, a, b, 2 * node + 1, dec);
    }

    int q1 = query_tree (inc, mid, a, b, 2 * node, dec);
    int q2 = query_tree (mid + 1, sf, a, b, 2 * node + 1, dec);

    return max (q1, q2);
}

void dfs (int node, int tata) {
    nivel[ node ] = nivel[ tata ] + 1;
    w[ node ] = 1;

    int pos, gr = -1;
    bool frunza = true;

    for (vector <int> :: iterator it = G[ node ].begin(); it != G[ node ].end(); ++it) {
        if (*it != tata) {
            frunza = false;
            dfs (*it, node);

            w[ node ] += w[ *it ];
            if (w[ *it ] > gr) {
                gr = w[ *it ];
                pos = *it;
            }
        }
    }

    if (frunza) {
        l[ node ] = ++NrLanturi;
        DimLant[ NrLanturi ] = 1;
        P[ NrLanturi ].push_back ( node );
    }

    else {
        l[ node ] = l[ pos ];
        ++DimLant[l[ node ]];
        P[l[ node ]].push_back ( node );

        for (vector <int> :: iterator it = G[ node ].begin(); it != G[ node ].end(); ++it) {
            if (*it != tata && l[ *it ] != l[ node ]) {
                TataLant[l[ *it ]] = node;
                NivLant[l[ *it ]] = nivel[ node ];
            }
        }
    }
}

void make_paths () {
    dfs (1, 0);
    for (int i = 1; i <= NrLanturi; ++i) {
        reverse (P[ i ].begin(), P[ i ].end());
        if (i > 1) {
            Dec[ i ] = Dec[i - 1] + 4 * DimLant[i - 1];
        }

        build_tree (1, DimLant[ i ], 1, Dec[ i ], i);
    }
}

void update (int x, int y) {
    update_tree (1, DimLant[l[ x ]], nivel[ x ] - NivLant[l[ x ]], y, 1, Dec[l[ x ]]);
}

void solve (int x, int y) {
    int ans = 0;
    while (1) {
        if (l[ x ] == l[ y ]) {
            if (nivel[ x ] > nivel[ y ])
                swap (x, y);

            ans = max (ans, query_tree (1, DimLant[l[ x ]], nivel[ x ] - NivLant[l[ x ]], nivel[ y ] - NivLant[l[ y ]], 1, Dec[l[ x ]]));

            g << ans << '\n';
            return;
        }

        if (NivLant[l[ x ]] < NivLant[l[ y ]])
            swap (x, y);

        ans = max (ans, query_tree (1, DimLant[l[ x ]], 1, nivel[ x ] - NivLant[l[ x ]], 1, Dec[l[ x ]]));
        x = TataLant[l[ x ]];
    }
}

int main() {
    f >> n >> m;
    for (int i = 1; i <= n; ++i) {
        f >> v[ i ];
    }

    for (int i = 1; i < n; ++i) {
        f >> x >> y;

        G[ x ].push_back ( y );
        G[ y ].push_back ( x );
    }

    make_paths ();
    for (int i = 1; i <= m; ++i) {
        f >> type >> x >> y;
        if (type == 0) {
            update (x, y);
        }

        else {
            solve (x, y);
        }
    }

    return 0;
}