Cod sursa(job #1177883)

Utilizator a_h1926Heidelbacher Andrei a_h1926 Data 26 aprilie 2014 13:45:19
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.89 kb
#include <fstream>
#include <vector>
#include <algorithm>

using namespace std;

const int NIL = -1;

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[size + x] = 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 {
        from = size + max(from, 0);
        to = size + min(to, size - 1);
        int maxValue = 0;
        while (from <= to) {
            maxValue = max(maxValue, max(tree[from], tree[to]));
            from = (from + 1) / 2;
            to = (to - 1) / 2;
        }
        return maxValue;
    }

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

vector< vector<int> > T, Paths;
int V;
vector<int> Values, Father, Size, Level, PathIndex, PathPosition;
vector<SegmentTree> SegmentTrees;

void DFS(const int x) {
    Size[x] = 1;
    int heaviestSon = NIL;
    for (vector<int>::const_iterator y = T[x].begin(); y != T[x].end(); ++y) {
        if (*y != Father[x]) {
            Father[*y] = x;
            Level[*y] = Level[x] + 1;
            DFS(*y);
            Size[x] += Size[*y];
            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];
    }
    PathPosition[x] = int(Paths[PathIndex[x]].size());
    Paths[PathIndex[x]].push_back(x);
}

void BuildHeavyPathDecomposition() {
    Father = vector<int>(V, NIL);
    Size = vector<int>(V, 0);
    Level = PathIndex = PathPosition = vector<int>(V, -1);
    Paths = vector< vector<int> >();
    Level[0] = 0;
    DFS(0);
}

void BuildSegmentTrees() {
    for (int i = 0; i < int(Paths.size()); ++i) {
        vector<int> pathValues;
        for (int j = 0; j < int(Paths[i].size()); ++j)
            pathValues.push_back(Values[Paths[i][j]]);
        SegmentTrees.push_back(SegmentTree(pathValues));
    }
}

inline int Query(int x, int y) {
    if (PathIndex[x] == PathIndex[y]) {
        if (PathPosition[x] > PathPosition[y])
            swap(x, y);
        return SegmentTrees[PathIndex[x]].Query(PathPosition[x], PathPosition[y]);
    }
    if (Level[Paths[PathIndex[x]].back()] < Level[Paths[PathIndex[y]].back()])
        swap(x, y);
    return max(Query(Father[Paths[PathIndex[x]].back()], y), SegmentTrees[PathIndex[x]].Query(PathPosition[x], int(Paths[PathIndex[x]].size()) - 1));
}

inline void AddEdge(const int x, const int y) {
    T[x].push_back(y);
    T[y].push_back(x);
}

int main() {
    ifstream in("heavypath.in");
    ofstream out("heavypath.out");
    int Q;
    in >> V >> Q;
    Values = vector<int>(V);
    for (int x = 0; x < V; ++x)
        in >> Values[x];
    T = vector< vector<int> >(V, vector<int>());
    for (int i = 1; i < V; ++i) {
        int x, y;
        in >> x >> y;
        AddEdge(x - 1, y - 1);
    }
    BuildHeavyPathDecomposition();
    BuildSegmentTrees();
    for (; Q > 0; --Q) {
        int type;
        in >> type;
        if (type == 0) {
            int x, v;
            in >> x >> v;
            SegmentTrees[PathIndex[x - 1]].Update(PathPosition[x - 1], v);
        } else {
            int x, y;
            in >> x >> y;
            out << Query(x - 1, y - 1) << "\n";
        }
    }
    in.close();
    out.close();
    return 0;
}