Cod sursa(job #1682253)

Utilizator RazvanR104Razvan-Andrei Ciocoiu RazvanR104 Data 10 aprilie 2016 03:17:52
Problema Heavy Path Decomposition Scor 10
Compilator cpp Status done
Runda Arhiva educationala Marime 3.86 kb
#include <bits/stdc++.h>

using namespace std;

const int minf = 0xffffffff, NMAX = 100010;

int N, M;
int tsize[NMAX], father[NMAX], level[NMAX], chpos, where[NMAX], V[NMAX], pos[NMAX];
vector<int> chain[NMAX], G[NMAX];

void DFS(int node, int from) {
    tsize[node] = 1;

    for (const int &it: G[node]) {
        if (it == from)
            continue;
        level[it] = level[node] + 1;
        father[it] = node;
        DFS(it, node);
        tsize[node] += tsize[it];
    }

    int maxpos = -1;
    for (const int &it: G[node]) {
        if (it == from)
            continue;
        if (maxpos == -1 || tsize[maxpos] < tsize[it])
            maxpos = it;
    }

    if (maxpos == -1) {
        where[node] = ++chpos;
        chain[chpos].push_back(node);
        pos[node] = chain[chpos].size() - 1;
    } else {
        where[node] = where[maxpos];
        chain[where[node]].push_back(node);
        pos[node] = chain[where[node]].size() - 1;
    }
}

struct Node {
    int v;
    Node *l, *r;

    Node(int v = 0, Node *l = 0, Node *r = 0):
        v(v),
        l(l),
        r(r) {
    }
} *ST[NMAX], *nil;

void Update(Node *curr, int left, int right, int pos, int value) {
    if (left == right) {
        curr->v = value;
        return;
    }
    int mid = (left + right) >> 1;
    if (pos <= mid)
        Update(curr->l, left, mid, pos, value);
    else
        Update(curr->r, mid + 1, right, pos, value);
    curr->v = max(curr->l->v, curr->r->v);
}

int Query(Node *curr, int left, int right, int qleft, int qright) {
    if (left >= qleft && right <= qright)
        return curr->v;
    if (left >= right)
        return minf;
    int mid = (left + right) >> 1, ret = minf;
    if (qleft <= mid)
        ret = max(ret, Query(curr->l, left, mid, qleft, qright));
    if (qright > mid)
        ret = max(ret, Query(curr->r, mid + 1, right, qleft, qright));
    return ret;
}

Node *Build(int left, int right, int ch) {
    if (left == right)
        return new Node(V[chain[ch][left]], nil, nil);
    int mid = (left + right) >> 1;
    Node *l = Build(left, mid, ch);
    Node *r = Build(mid + 1, right, ch);
    return new Node(max(l->v, r->v), l, r);
}

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

    int i, j;
    int x, y;

    nil = new Node(minf);
    nil->l = nil->r = nil;

    cin >> N >> M;
    for (i = 1; i <= N; ++i)
        cin >> V[i];
    for (i = 1; i < N; ++i) {
        cin >> x >> y;
        G[x].push_back(y);
        G[y].push_back(x);
    }

    DFS(1, -1);
    for (i = 1; i <= chpos; ++i)
        ST[i] = Build(0, chain[i].size() - 1, i);

    father[1] = 1;
    while (M--) {
        int type;
        cin >> type >> x >> y;
        if (type == 0)
            Update(ST[where[x]], 0, chain[where[x]].size() - 1, pos[x], y);
        else {
            int answer = minf;
            if (level[x] < level[y])
                swap(x, y);

            if (where[x] == where[y]) {
                answer = max(answer, Query(ST[where[x]], 0, chain[where[x]].size() - 1, pos[x], pos[y]));
                goto PrintAnswer;
            }

            while (where[x] != where[y]) {
                if (level[x] < level[y])
                    swap(x, y);

                answer = max(answer, Query(ST[where[x]], 0, chain[where[x]].size() - 1, pos[x], chain[where[x]].size() - 1));
                x = father[chain[where[x]].back()];
            }

            if (level[x] < level[y])
                swap(x, y);

            if (where[x] == where[y]) {
                answer = max(answer, Query(ST[where[x]], 0, chain[where[x]].size() - 1, pos[x], pos[y]));
                goto PrintAnswer;
            }

            PrintAnswer: cout << answer << '\n';
        }
    }

    return 0;
}