Cod sursa(job #809196)

Utilizator PlayLikeNeverB4George Marcus PlayLikeNeverB4 Data 7 noiembrie 2012 23:59:20
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.11 kb
#include <cstdio>
#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <sstream>
#include <iomanip>
#include <cmath>
#include <cstdlib>
#include <ctype.h>
#include <cstring>
#include <ctime>

using namespace std;

#define MAXN 100005
int N, M, t, x, y;
int val[MAXN];
vector<int> A[MAXN];
int T[MAXN];
int lvl[MAXN];
int Aint[4 * MAXN];
bool viz[MAXN];
vector<int> lant[MAXN];
int nrLant;
int inLant[MAXN];
int pos[MAXN];
int szLant[MAXN];
int offset[MAXN];
int tataLant[MAXN];

int dfs(int node, int prev) {
    viz[node] = true;
    T[node] = prev;
    lvl[node] = lvl[prev] + 1;

    int maxNrFii = 0;
    int pmax = -1;
    int nrFii = 0;
    int crt;
    for(vector<int> :: iterator it = A[node].begin(); it != A[node].end(); it++)
        if(!viz[*it]) {
            crt = dfs(*it, node);
            nrFii += crt;
            if(crt > maxNrFii) {
                maxNrFii = crt;
                pmax = *it;
            }
        }

    if(maxNrFii == 0) {
        inLant[node] = nrLant;
        lant[nrLant].push_back(node);
        szLant[nrLant] = 1;
        nrLant++;
    }
    else {
        int Lmax = inLant[pmax];
        inLant[node] = Lmax;
        lant[Lmax].push_back(node);
        szLant[Lmax]++;
    }

    return nrFii + 1;
}

void init(int k, int st, int dr, int off, int idxLant) {
    if(st == dr) {
        Aint[off + k] = val[lant[idxLant][st - 1]];
        return;
    }

    int m = (st + dr) / 2;
    init(2 * k, st, m, off, idxLant);
    init(2 * k + 1, m + 1, dr, off, idxLant);

    Aint[off + k] = max(Aint[off + 2 * k], Aint[off + 2 * k + 1]);
}

void update(int k, int st, int dr, int off, int qpos) {
    if(st == dr) {
        Aint[off + k] = y;
        return;
    }

    int m = (st + dr) / 2;
    if(qpos <= m)
        update(2 * k, st, m, off, qpos);
    else
        update(2 * k + 1, m + 1, dr, off, qpos);

    Aint[off + k] = max(Aint[off + 2 * k], Aint[off + 2 * k + 1]);
}

int query(int k, int st, int dr, int qst, int qdr, int off) {
    if(qst <= st && dr <= qdr) {
        return Aint[off + k];
    }

    int m = (st + dr) / 2;
    int ret = 0;
    if(qst <= m)
        ret = max(ret, query(2 * k, st, m, qst, qdr, off));
    if(qdr > m)
        ret = max(ret, query(2 * k + 1, m + 1, dr, qst, qdr, off));

    return ret;
}

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

    scanf("%d %d", &N, &M);
    for(int i = 1; i <= N; i++)
        scanf("%d", &val[i]);
    for(int i = 0; i < N - 1; i++) {
        scanf("%d %d", &x, &y);
        A[x].push_back(y);
        A[y].push_back(x);
    }

    lvl[0] = 0;
    dfs(1, 0);

    offset[0] = 0;
    for(int i = 0; i < nrLant; i++) {
        if(i > 0)
            offset[i] = offset[i - 1] + 4 * szLant[i - 1];
        reverse(lant[i].begin(), lant[i].end());
        init(1, 1, (int)lant[i].size(), offset[i], i);
        for(vector<int> :: iterator it = lant[i].begin(); it != lant[i].end(); it++)
            pos[*it] = (it - lant[i].begin()) + 1;
    }
    for(int i = 1; i <= N; i++)
        tataLant[i] = T[lant[inLant[i]][0]];

    for(int i = 0; i < M; i++) {
        scanf("%d %d %d", &t, &x, &y);

        if(t == 1) {
            int ans = 0;
            while(true) {
                if(inLant[x] == inLant[y]) {
                    int left = min(pos[x], pos[y]);
                    int right = max(pos[x], pos[y]);
                    ans = max(ans, query(1, 1, szLant[inLant[x]], left, right, offset[inLant[x]]));
                    break;
                }

                if(lvl[tataLant[x]] < lvl[tataLant[y]])
                    swap(x, y);

                ans = max(ans, query(1, 1, szLant[inLant[x]], 1, pos[x], offset[inLant[x]]));
                x = tataLant[x];
            }

            printf("%d\n", ans);
        }
        else {
            int crtL = inLant[x];
            update(1, 1, szLant[crtL], offset[crtL], pos[x]);
        }
    }

	return 0;
}