Cod sursa(job #1198682)

Utilizator a_h1926Heidelbacher Andrei a_h1926 Data 16 iunie 2014 17:44:14
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.05 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) {
        if (where < 0 || where >= size)
            return;
        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 = max(0, from);
        to = min(size - 1, to);
        if (from > to)
            return 0;
        from += size;
        to += size;
        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> Value, Father, Size, Level, PathIndex, PathPosition;
vector<SegmentTree> SegmentTrees;

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

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(SegmentTrees[PathIndex[x]].Query(PathPosition[x], int(Paths[PathIndex[x]].size()) - 1), Query(Father[Paths[PathIndex[x]].back()], y));
}

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

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