Cod sursa(job #1112414)

Utilizator a_h1926Heidelbacher Andrei a_h1926 Data 19 februarie 2014 19:18:03
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 6.24 kb
#include <cstdio>
#include <cassert>

#include <vector>
#include <algorithm>

using namespace std;

class SegmentTree {
  public:
    SegmentTree(const vector<int> &values):
      size(1),
      tree(vector<int>()) {
        for (; size < int(values.size()); size *= 2);
        tree = vector<int>(2 * size, 0);
        for (int x = 0; x < int(values.size()); ++x)
            tree[x + size] = values[x];
        for (int x = size - 1; x > 0; --x)
            tree[x] = max(tree[2 * x], tree[2 * x + 1]);
    }

    void Update(int where, const int value) {
        tree[where += size] = value;
        for (where /= 2; where > 0; where /= 2)
            tree[where] = max(tree[2 * where], tree[2 * where + 1]);
    }

    int Query(int from, int to) const {
        int answer = 0;
        from += size;
        to += size;
        while (from <= to) {
            answer = max(answer, max(tree[from], tree[to]));
            from = (from + 1) / 2;
            to = (to - 1) / 2;
        }
        return answer;
    }

  private:
    int size;
    vector<int> tree;
};

class Tree {
  public:
    static const int NIL = -1;

    Tree():
      v(0),
      root(NIL),
      edges(vector< vector<int> >()),
      father(vector<int>()),
      size(vector<int>()),
      level(vector<int>()) {}

    Tree(const int _v, const int _root, const vector< pair<int, int> > &_edges):
      v(_v),
      root(_root),
      edges(vector< vector<int> >(_v, vector<int>())),
      father(vector<int>(_v, NIL)),
      size(vector<int>(_v, 0)),
      level(vector<int>(_v, NIL)) {
        for (int i = 0; i < int(_edges.size()); ++i) {
            edges[_edges[i].first].push_back(_edges[i].second);
            edges[_edges[i].second].push_back(_edges[i].first);
        }
        father[root] = NIL;
        level[root] = 0;
        InitializeDFS(root);
    }

    int V() const {
        return v;
    }

    int Root() const {
        return root;
    }

    vector<int>::const_iterator EdgesBegin(const int x) const {
        return edges[x].begin();
    }

    vector<int>::const_iterator EdgesEnd(const int x) const {
        return edges[x].end();
    }

    int Father(const int x) const {
        return father[x];
    }

    int Size(const int x) const {
        return size[x];
    }

    int Level(const int x) const {
        return level[x];
    }

    void GetHeavyPathDecomposition(vector< vector<int> > &paths, vector<int> &pathIndex, vector<int> &pathPosition) const {
        pathIndex = pathPosition = vector<int>(v, NIL);
        DFS(root, paths, pathIndex);
        for (int i = 0; i < int(paths.size()); ++i) {
            reverse(paths[i].begin(), paths[i].end());
            for (int j = 0; j < int(paths[i].size()); ++j)
                pathPosition[paths[i][j]] = j;
        }
    }

    vector< vector<int> > GetHeavyPathDecomposition() const {
        vector< vector<int> > paths;
        vector<int> pathIndex, pathPosition;
        GetHeavyPathDecomposition(paths, pathIndex, pathPosition);
        return paths;
    }

  private:
    int v, root;
    vector< vector<int> > edges;
    vector<int> father, size, level;

    void InitializeDFS(const int x) {
        size[x] = 1;
        for (vector<int>::const_iterator y = edges[x].begin(); y != edges[x].end(); ++y) {
            if (*y != father[x]) {
                father[*y] = x;
                level[*y] = level[x] + 1;
                InitializeDFS(*y);
                size[x] += size[*y];
            }
        }
    }

    void DFS(const int x, vector< vector<int> > &paths, vector<int> &pathIndex) const {
        int heaviestSon = NIL;
        for (vector<int>::const_iterator y = edges[x].begin(); y != edges[x].end(); ++y) {
            if (*y != father[x]) {
                DFS(*y, paths, pathIndex);
                if (heaviestSon == NIL || size[*y] > size[heaviestSon])
                    heaviestSon = *y;
            }
        }
        if (heaviestSon == NIL) {
            pathIndex[x] = int(paths.size());
            paths.push_back(vector<int>());
        } else {
            pathIndex[x] = pathIndex[heaviestSon];
        }
        paths[pathIndex[x]].push_back(x);
    }
};

Tree T;
vector< vector<int> > Paths;
vector<int> Values, PathIndex, PathPosition;
vector<SegmentTree> SegmentTrees;
int Q;

inline int QueryPath(int from, int to) {
    if (PathIndex[from] == PathIndex[to]) {
        if (T.Level(from) > T.Level(to))
            swap(from, to);
        return SegmentTrees[PathIndex[from]].Query(PathPosition[from], PathPosition[to]);
    }
    if (T.Level(Paths[PathIndex[from]].front()) > T.Level(Paths[PathIndex[to]].front()))
        swap(from, to);
    return max(SegmentTrees[PathIndex[to]].Query(0, PathPosition[to]), QueryPath(from, T.Father(Paths[PathIndex[to]].front())));
}

void Solve() {
    T.GetHeavyPathDecomposition(Paths, PathIndex, PathPosition);
    for (int i = 0; i < int(Paths.size()); ++i) {
        vector<int> pathValues = vector<int>(int(Paths[i].size()));
        for (int j = 0; j < int(Paths[i].size()); ++j)
            pathValues[j] = Values[Paths[i][j]];
        SegmentTrees.push_back(SegmentTree(pathValues));
    }
    for (; Q > 0; --Q) {
        int type;
        assert(scanf("%d", &type) == 1);
        if (type == 0) {
            int node, value;
            assert(scanf("%d %d", &node, &value) == 2);
            --node;
            SegmentTrees[PathIndex[node]].Update(PathPosition[node], Values[node] = value);
        } else {
            int from, to;
            assert(scanf("%d %d", &from, &to) == 2);
            printf("%d\n", QueryPath(--from, --to));
        }
    }
}

void Read() {
    int v;
    assert(scanf("%d %d", &v, &Q) == 2);
    Values = vector<int>(v);
    for (int x = 0; x < v; ++x)
        assert(scanf("%d", &Values[x]) == 1);
    vector< pair<int, int> > edges;
    for (int i = 1; i < v; ++i) {
        int x, y;
        assert(scanf("%d %d", &x, &y) == 2);
        edges.push_back(make_pair(--x, --y));
    }
    T = Tree(v, 0, edges);
}

int main() {
    assert(freopen("heavypath.in", "r", stdin));
    assert(freopen("heavypath.out", "w", stdout));
    Read();
    Solve();
    return 0;
}