Cod sursa(job #1164254)

Utilizator a_h1926Heidelbacher Andrei a_h1926 Data 1 aprilie 2014 22:56:51
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.81 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 SetValue(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 maxValue = 0;
        from += size;
        to += size;
        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, Root, Q;
vector<int> Father, Size, Depth, Values, 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])
            continue;
        Father[*y] = x;
        Depth[*y] = Depth[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() {
    Size = Depth = vector<int>(V, 0);
    Father = PathIndex = PathPosition = vector<int>(V, NIL);
    DFS(Root);
    for (int p = 0; p < int(Paths.size()); ++p) {
        vector<int> pathValues = vector<int>(int(Paths[p].size()));
        for (int i = 0; i < int(Paths[p].size()); ++i)
            pathValues[i] = Values[Paths[p][i]];
        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 (Depth[Paths[PathIndex[x]].back()] < Depth[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);
}

void ReadTree(ifstream &cin) {
    T = vector< vector<int> >(V, vector<int>());
    Values = vector<int>(V);
    for (int x = 0; x < V; ++x)
        cin >> Values[x];
    for (int i = 1; i < V; ++i) {
        int x, y;
        cin >> x >> y;
        AddEdge(x - 1, y - 1);
    }
    Root = 0;
}

int main() {
    ifstream cin("heavypath.in");
    ofstream cout("heavypath.out");
    cin >> V >> Q;
    ReadTree(cin);
    BuildHeavyPathDecomposition();
    for (; Q > 0; --Q) {
        int type;
        cin >> type;
        if (type == 0) {
            int x, value;
            cin >> x >> value;
            --x;
            SegmentTrees[PathIndex[x]].SetValue(PathPosition[x], Values[x] = value);
        } else {
            int x, y;
            cin >> x >> y;
            cout << Query(--x, --y) << "\n";
        }
    }
    return 0;
}