Cod sursa(job #1279500)

Utilizator valentin.harsanValentin Harsan valentin.harsan Data 30 noiembrie 2014 14:47:41
Problema Heavy Path Decomposition Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 3.3 kb
#include<iostream>
#include<fstream>
#include<algorithm>
#include<vector>
#include<cstring>
using namespace std;

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

const int N = 100100;

int n, m, x[N], sizeSubArb[N], niv[N];
vector<int> v[N];
bool ver[N];

void calcSiz(int nod) {
    ver[nod] = 1;
    sizeSubArb[nod] = 1;

    for(vector<int>::iterator it = v[nod].begin(); it != v[nod].end(); ++it) if(!ver[*it]) {
        niv[*it] = niv[nod] + 1;
        calcSiz(*it);
        sizeSubArb[nod] += sizeSubArb[*it];
    }
}

int nrl, lant[N], size[N], pozNod[N], pLant[N], firstNod[N];
vector<int> aint[N];

void calcLant(int nod, int lantc) {
    ver[nod] = 1;
    pozNod[nod] = ++size[lantc];
    lant[nod] = lantc;

    int sizMax = 0;

    for(vector<int>::iterator it = v[nod].begin(); it != v[nod].end(); ++it) if(!ver[*it])
        sizMax = max(sizMax, sizeSubArb[*it]);

    for(vector<int>::iterator it = v[nod].begin(); it != v[nod].end(); ++it) if(!ver[*it] && sizeSubArb[*it] == sizMax) {
        calcLant(*it, lantc);
        break;
    }

    for(vector<int>::iterator it = v[nod].begin(); it != v[nod].end(); ++it) if(!ver[*it]) {
        ++nrl;
        firstNod[nrl] = *it;
        pLant[nrl] = nod;
        calcLant(*it, nrl);
    }
}

void update(int lant, int nod, int pozx, int pozy, int poz, int val) {
    if(pozx == pozy) {
        aint[lant][nod] = val;
        return;
    }

    int mid = (pozx + pozy) / 2;

    if(mid >= poz)
        update(lant, 2 * nod, pozx, mid, poz, val);
    else
        update(lant, 2 * nod + 1, mid + 1, pozy, poz, val);

    aint[lant][nod] = max(aint[lant][2 * nod], aint[lant][2 * nod + 1]);
}

int query(int lant, int nod, int pozx, int pozy, int poz1, int poz2) {
    if(poz1 > poz2)
        swap(poz1, poz2);

    if(poz1 <= pozx && pozy <= poz2)
        return aint[lant][nod];

    int mid = (pozx + pozy) / 2, rez = 0;

    if(mid >= poz1)
        rez = query(lant, 2 * nod, pozx, mid, poz1, poz2);
    if(mid < poz2)
        rez = max(rez, query(lant, 2 * nod + 1, mid + 1, pozy, poz1, poz2));

    return rez;
}

int maxLant(int nod1, int nod2) {
    int rez = 0;

    while(lant[nod1] != lant[nod2]) {
        if(niv[firstNod[lant[nod1]]] < niv[firstNod[lant[nod2]]])
            swap(nod1, nod2);

        rez = max(rez, query(lant[nod1], 1, 1, size[lant[nod1]], 1, pozNod[nod1]));
        nod1 = pLant[lant[nod1]];
    }

    rez = max(rez, query(lant[nod1], 1, 1, size[lant[nod1]], pozNod[nod1], pozNod[nod2]) );

    return rez;
}

int main() {
    int i;

    in >> n >> m;

    for(i = 1; i <= n; ++i)
        in >> x[i];

    for(i = 1; i < n; ++i) {
        int a, b;
        in >> a >> b;

        v[a].push_back(b);
        v[b].push_back(a);
    }

    calcSiz(1);

    memset(ver, 0, sizeof(ver));
    firstNod[1] = 1;
    calcLant(1, ++nrl);
    for(i = 1; i <= nrl; ++i)
        aint[i].resize(4 * size[i]);

    for(i = 1; i <= n; ++i)
        update(lant[i], 1, 1, size[lant[i]], pozNod[i], x[i]);

    for(i = 1; i <= m; ++i) {
        int op, a, b;

        in >> op >> a >> b;

        if(!op)
            update(lant[a], 1, 1, size[lant[a]], pozNod[a], b);
        else
            cout << maxLant(a, b) << "\n";
    }

    return 0;
}