Cod sursa(job #1386850)

Utilizator valentin.harsanValentin Harsan valentin.harsan Data 13 martie 2015 13:24:35
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.94 kb
#include<iostream>
#include<fstream>
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<queue>
#include<map>
#include<set>
#include<algorithm>
#include<iomanip>
#include<bitset>
using namespace std;

const int N = 101000;
const int inf = 2000000000;

struct aint {
    vector<int> smax;
    int n;

    aint(int nn) {
        n = nn;
        smax.resize(4 * n + 6);
    }

    void _update(int nod, int pozx, int pozy, int poz1, int poz2, int val) {
        if(pozx >= poz1 && poz2 >= pozy) {
            smax[nod] = val;
            return;
        }

        int mid = (pozx + pozy) / 2;

        if(mid >= poz1)
            _update(2 * nod, pozx, mid, poz1, poz2, val);
        if(mid < poz2)
            _update(2 * nod + 1, mid + 1, pozy, poz1, poz2, val);

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

    void update(int pozx, int pozy, int val) {_update(1, 1, n, pozx, pozy, val);}

    int _query(int nod, int pozx, int pozy, int poz1, int poz2) {
        if(pozx >= poz1 && poz2 >= pozy)
            return smax[nod];

        int r = -inf, mid = (pozx + pozy) / 2;

        if(mid >= poz1)
            r = _query(2 * nod, pozx, mid, poz1, poz2);
        if(mid < poz2)
            r = max(r, _query(2 * nod + 1, mid + 1, pozy, poz1, poz2));

        return r;
    }

    int query(int pozx, int pozy) {
        if(pozx > pozy)
            swap(pozx, pozy);
        if(!pozy)
            return 0;

        return _query(1, 1, n, pozx, pozy);
    }
};

int n, m;
vector<int> v[N];

int nrel[N], cs[N], cd[N], te, niv[N];
int val[N];

void calc1(int nod) {
    nrel[nod] = 1;
    cs[nod] = ++te;

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

        calc1(*it);
        nrel[nod] += nrel[*it];
    }

    cd[nod] = te;
}

int lantc, sizeLant[N], nl[N], pozNod[N], lastNod[N];
vector<aint> arb;

void calch(int nod, int par, int la, int pozz) {
    int smax = 0, elmax;
    vector<int>::iterator it;

    pozNod[nod] = pozz;
    sizeLant[la]++;
    nl[nod] = la;

    for(it = v[nod].begin(); it != v[nod].end(); ++it) if(*it != par)
        if(nrel[*it] > smax) {
            smax = nrel[*it];
            elmax = *it;
        }

    for(it = v[nod].begin(); it != v[nod].end(); ++it) if(*it != par) {

        if(*it == elmax) {
            calch(*it, nod, la, pozz + 1);
        }
        else {
            ++lantc;
            lastNod[lantc] = nod;

            calch(*it, nod, lantc, 1);
        }
    }
}

void update(int nod, int val) {

    arb[nl[nod]].update(pozNod[nod], pozNod[nod], val);
}

int query(int nod1, int nod2) {

    int rez = -inf;

    while(nl[nod1] != nl[nod2]) {
        if(niv[lastNod[ nl[nod1] ]] > niv[lastNod[ nl[nod2] ]])
            swap(nod1, nod2);

        int t = arb[nl[nod2]].query(1, pozNod[nod2]);

        rez = max(rez, t);

        nod2 = lastNod[nl[nod2]];
    }

    rez = max(rez, arb[nl[nod2]].query(pozNod[nod1], pozNod[nod2]));

    return rez;
}

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

    cin >> n >> m;

    for(i = 1; i <= n; ++i)
        cin >> val[i];

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

    calc1(1);

    niv[0] = -1;

    lantc = 0;
    calch(1, 0, 0, 1);
    for(i = 0; i <= lantc; ++i) {
        arb.push_back(*(new aint(sizeLant[i])));
    }
    for(i = 1; i <= n; ++i)
        update(i, val[i]);

    for(i = 1; i <= m; ++i) {
        int a;
        int c, d;
        scanf("%d", &a);
        scanf("%d%d", &c, &d);

        if(a == 0) {
             update(c, d);
        }
        else {
            cout << query(c, d) << "\n";
        }
    }

    return 0;
}