Cod sursa(job #1518558)

Utilizator AlexandruValeanuAlexandru Valeanu AlexandruValeanu Data 5 noiembrie 2015 23:02:56
Problema Heavy Path Decomposition Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 4.22 kb
#include <bits/stdc++.h>

using namespace std;

class SegmentTree
{
public:

    vector<int> tree;
    int N;

    SegmentTree(const vector<int> &values)
    {
        this->N = values.size();

        int pw = 1;

        while (pw <= this->N)
            pw *= 2;

        tree.resize(pw, 0);

        build(1, 0, N - 1, values);
    }

    void build(int node, int st, int dr, const vector<int> &key)
    {
        if (st == dr)
            tree[node] = key[st];
        else
        {
            int m = (st + dr) / 2;

            build(2 * node, st, m, key);
            build(2 * node + 1, m + 1, dr, key);

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

    void update(int node, int st, int dr, const int pos, const int value)
    {
        if (st == dr)
            tree[node] = value;
        else
        {
            int m = (st + dr) / 2;

            if (pos <= m)
                update(2 * node, st, m, pos, value);
            else
                update(2 * node + 1, m + 1, dr, pos, value);

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

    int query(int node, int st, int dr, const int l, const int r) const
    {
        if (l <= st && dr <= r)
            return tree[node];
        else
        {
            int m = (st + dr) / 2;
            int sol = numeric_limits<int>::min();

            if (l <= m)
                sol = max(sol, query(2 * node, st, m, l, r));

            if (m < r)
                sol = max(sol, query(2 * node + 1, m + 1, dr, l, r));

            return sol;
        }
    }

    void update(const int position, const int key)
    {
        update(1, 0, N - 1, position, key);
    }

    int query(const int x, const int y) const
    {
        return query(1, 0, N - 1, x, y);
    }
};

const int MAX_N = 100000 + 1;

vector<int> G[MAX_N];
vector<SegmentTree> ST;

int depth[MAX_N], father[MAX_N], size[MAX_N], valueNode[MAX_N];
int path[MAX_N], posInPath[MAX_N], startNode[MAX_N], lengthPath[MAX_N];

int N, Q;
int numberOfPaths;

void dfs(int node)
{
    int hson = 0;
    size[node] = 1;

    for (const int v : G[node])
    {
        if (father[v] == 0)
        {
            father[v] = node;
            depth[v] = depth[node] + 1;

            dfs(v);

            size[node] += size[v];

            if (size[hson] < size[v])
                hson = v;
        }
    }

    if (hson == 0)
        path[node] = numberOfPaths++;
    else
        path[node] = path[hson];

    posInPath[node] = lengthPath[ path[node] ]++;
}

void build_heavy()
{
    father[1] = 1;
    depth[1] = 0;

    dfs(1);

    for (int i = 1; i <= N; ++i)
    {
        posInPath[i] = lengthPath[ path[i] ] - posInPath[i] - 1;

        if (posInPath[i] == 0)
            startNode[ path[i] ] = i;
    }
}

void build_segment_trees()
{
    vector<vector<int>> pathValues(numberOfPaths);

    for (int i = 0; i < numberOfPaths; ++i)
        pathValues[i].resize(lengthPath[i], 0);

    for (int i = 1; i <= N; ++i)
        pathValues[ path[i] ][ posInPath[i] ] = valueNode[i];

    for (int i = 0; i < numberOfPaths; ++i)
        ST.push_back(SegmentTree(pathValues[i]));
}

void updateNode(const int node, const int key)
{
    valueNode[node] = key;

    ST[ path[node] ].update(posInPath[node], key);
}

int query(int x, int y)
{
    if (depth[ startNode[ path[x] ] ] < depth[ startNode[ path[y] ] ])
        swap(x, y);

    if (path[x] == path[y])
        return ST[ path[x] ].query(min(posInPath[x], posInPath[y]), max(posInPath[x], posInPath[y]));
    else
        return max(ST[ path[x] ].query(0, posInPath[x]), query(father[ startNode[ path[x] ] ], y));
}

int main()
{
    ifstream in("heavypath.in");
    ofstream out("heavypath.out");

    ios_base::sync_with_stdio(false);

    in >> N >> Q;

    for (int i = 1; i <= N; ++i)
        in >> valueNode[i];

    for (int i = 0; i < N - 1; ++i)
    {
        int x, y;
        in >> x >> y;

        G[x].emplace_back(y);
        G[y].emplace_back(x);
    }

    build_heavy();
    build_segment_trees();

    for (int i = 0; i < Q; ++i)
    {
        int t, x, y;
        in >> t >> x >> y;

        if (t == 0)
        {
            updateNode(x, y);
        }
        else
        {
            out << query(x, y) << "\n";
        }
    }

    return 0;
}