Cod sursa(job #1195595)

Utilizator RazvanR104Razvan-Andrei Ciocoiu RazvanR104 Data 8 iunie 2014 00:25:35
Problema Heavy Path Decomposition Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 3.91 kb
#include <iostream>
#include <iomanip>
#include <fstream>

#include <algorithm>
#include <bitset>
#include <deque>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <utility>
#include <vector>

#if __cplusplus > 199711L
#include <unordered_map>
#include <unordered_set>
#endif

#include <cstdio>
#include <ctime>
#include <cmath>
#include <cstring>
#include <cstdlib>

using namespace std;

typedef long long int64;

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

const int NMAX = 100010, inf = 0x3f3f3f3f;

int N, M, nr_l;
int value[NMAX], l[NMAX], lLVL[NMAX], lFATH[NMAX], lSZ[NMAX], lW[NMAX], LVL[NMAX], tree[4 * NMAX], tOffset[NMAX], father[NMAX];

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

bool visited[NMAX];

void DF(const int node)
{
    int it, lN = -1, _node;

    visited[node] = true;
    for(it = 0; it < (int)G[node].size(); ++it)
    {
        _node = G[node][it];
        if (visited[_node]) continue;

        LVL[_node] = LVL[node] + 1;
        father[_node] = node;

        DF(_node);

        if (lN == -1 || lW[lN] < lW[_node])
            lN = _node;
    }

    if (lN == -1)
    {
        l[node] = ++nr_l;
        lSZ[nr_l] = 1;
        P[nr_l].push_back(node);
        return;
    }

    lW[node] = lW[lN] + 1;
    l[node] = l[lN];
    ++lSZ[l[node]];
    P[l[node]].push_back(node);

    for (it = 0; it < (int)G[node].size(); ++it)
    {
        _node = G[node][it];
        if (LVL[_node] < LVL[node] || _node == lN) continue;
        lFATH[l[_node]] = node;
        lLVL[l[_node]] = LVL[node];
    }
}

void update(const int node, const int left, const int right, const int pos, const int value, const int offset)
{
    if (left == right)
    {
        tree[node + offset] = value;
        return;
    }

    int div = (left + right) >> 1;

    if (pos <= div) update(node * 2, left, div, pos, value, offset);
    else update(node * 2 + 1, div + 1, right, pos, value, offset);

    tree[node + offset] = max(tree[node * 2 + offset], tree[node * 2 + 1 + offset]);
}

int query(const int node, const int left, const int right, const int qleft, const int qright, const int offset)
{
    if (left >= qleft && right <= qright)
        return tree[node + offset];

    int ret = -inf;

    int div = (left + right) >> 1;
    if (qleft <= div) ret = max(ret, query(node * 2, left, div, qleft, qright, offset));
    if (qright > div) ret = max(ret, query(node * 2 + 1, div + 1, right, qleft, qright, offset));

    return ret;
}

int main()
{
    int i, j, x, y, op, a, b;

    fin >> N >> M;

    for (i = 1; i <= N; ++i)
        fin >> value[i];

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

    LVL[1] = 1;
    DF(1);

    for (i = 1; i <= nr_l; ++i)
    {
        reverse(P[i].begin(), P[i].end());
        tOffset[i] = tOffset[i - 1] + lSZ[i - 1] * 4;

        for (j = 0; j < lSZ[i]; ++j)
            update(1, 1, lSZ[i], j + 1, value[P[i][j]], tOffset[i]);
    }

    int res;

    while(M--)
    {
        fin >> op >> a >> b;

        if (op == 0)
            update(1, 1, lSZ[l[a]], LVL[a] - lLVL[l[a]], b, tOffset[l[a]]);
        else
        {
            res = -inf;
            while(true)
            {
                if (l[a] == l[b])
                {
                    if (LVL[a] > LVL[b]) swap(a, b);
                    res = max(res, query(1, 1, lSZ[l[a]], LVL[a] - lLVL[l[a]], LVL[b] - lLVL[l[a]], tOffset[l[a]]));
                    break;
                }

                if (lLVL[l[a]] < lLVL[l[b]]) swap(a, b);
                res = max(res, query(1, 1, lSZ[l[a]], 1, LVL[a] - lLVL[l[a]], tOffset[l[a]]));
                a = father[a];
            }
            fout << res << '\n';
        }
    }

    fin.close();
    fout.close();
    return 0;
}