Cod sursa(job #986715)

Utilizator a_h1926Heidelbacher Andrei a_h1926 Data 19 august 2013 14:05:35
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.01 kb
#include <fstream>
#include <algorithm>
#include <vector>

using namespace std;

const int NIL = -1;

template<class IntType>
class SegmentTree {
  public:
    SegmentTree(const vector<IntType> &values) {
        for (size = 1; size < int(values.size()); size *= 2);
        tree = vector<IntType>(2 * size + 1, 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 IntType value) {
        tree[where += size] = value;
        for (where /= 2; where > 0; where /= 2)
            tree[where] = max(tree[2 * where], tree[2 * where + 1]);
    }

    IntType QueryMax(int from, int to) const {
        IntType 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<IntType> tree;
};

vector< vector<int> > Tree;
int V, Q;
vector<int> Values, Father, Level, Size, PathIndex, Position, Begin;
vector< vector<int> > Paths;
vector< SegmentTree<int> > SegmentTrees;

void DFS(const int x) {
    Size[x] = 1;
    int heaviestSon = NIL;
    for (const auto &y: Tree[x]) {
        if (Father[y] == NIL) {
            Father[y] = x;
            Level[y] = Level[x] + 1;
            DFS(y);
            Size[x] += Size[y];
            if (heaviestSon == NIL || Size[heaviestSon] < Size[y])
                heaviestSon = y;
        }
    }
    if (heaviestSon == NIL) {
        Paths.push_back(vector<int>());
        PathIndex[x] = int(Paths.size()) - 1;
    } else {
        PathIndex[x] = PathIndex[heaviestSon];
    }
    Paths[PathIndex[x]].push_back(x);
}

void BuildHeavyPathDecomposition() {
    for (auto &f: Father)
        f = NIL;
    Father[0] = 0;
    Level[0] = 0;
    DFS(0);
    Begin = vector<int>(int(Paths.size()), NIL);
    for (int p = 0; p < int(Paths.size()); ++p) {
        reverse(Paths[p].begin(), Paths[p].end());
        for (int i = 0; i < int(Paths[p].size()); ++i)
            Position[Paths[p][i]] = i;
        Begin[p] = Paths[p][0];
    }
}

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

int QueryPath(int x, int y) {
    if (Level[Begin[PathIndex[x]]] < Level[Begin[PathIndex[y]]])
        swap(x, y);
    if (PathIndex[x] == PathIndex[y])
        return SegmentTrees[PathIndex[x]].QueryMax(min(Position[x], Position[y]), max(Position[x], Position[y]));
    return max(SegmentTrees[PathIndex[x]].QueryMax(0, Position[x]), QueryPath(Father[Begin[PathIndex[x]]], y));
}

void Solve(ifstream &cin, ofstream &cout) {
    BuildHeavyPathDecomposition();
    BuildSegmentTrees();
    for (; Q > 0; --Q) {
        int type, x, y;
        cin >> type >> x >> y;
        if (type == 0) {
            --x;
            Values[x] = y;
            SegmentTrees[PathIndex[x]].SetValue(Position[x], y);
        } else {
            --x;
            --y;
            cout << QueryPath(x, y) << "\n";
        }
    }
}

void ReadTree(ifstream &cin) {
    cin >> V >> Q;
    Tree = vector< vector<int> >(V, vector<int>());
    Values = Father = Level = Size = PathIndex = Position = vector<int>(V, 0);
    for (int x = 0; x < V; ++x)
        cin >> Values[x];
    for (int i = 1; i < V; ++i) {
        int x, y;
        cin >> x >> y;
        --x;
        --y;
        Tree[x].push_back(y);
        Tree[y].push_back(x);
    }
}

int main() {
    ifstream cin("heavypath.in");
    ofstream cout("heavypath.out");
    ReadTree(cin);
    Solve(cin, cout);
    cin.close();
    cout.close();
    return 0;
}