Cod sursa(job #947799)

Utilizator a_h1926Heidelbacher Andrei a_h1926 Data 8 mai 2013 16:05:41
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.5 kb
#include <fstream>
#include <algorithm>
#include <vector>

using namespace std;

typedef vector<int>::iterator it;

const int MAX_N = 100005;
const int oo = 0x3f3f3f3f;
const int NIL = -1;

class SegmentTree {
  public:
    SegmentTree() {
        size = 0;
        tree = vector<int>();
    }

    SegmentTree(vector<int> &values) {
        size = static_cast<int>(values.size());
        int capacity = 1;
        for (; capacity <= size; capacity *= 2);
        tree = vector<int>(2 * capacity + 1);
        BuildTree(1, 0, size - 1, values);
    }

    void Update(int position, int value) {
        Update(1, 0, size - 1, position, value);
    }

    int Query(int left, int right) {
        return Query(1, 0, size - 1, left, right);
    }

  private:
    int size;
    vector<int> tree;

    void BuildTree(int index, int left, int right, vector<int> &values) {
        int middle = (left + right) / 2;
        if (left == right) {
            tree[index] = values[middle];
            return;
        }
        BuildTree(2 * index, left, middle, values);
        BuildTree(2 * index + 1, middle + 1, right, values);
        tree[index] = max(tree[2 * index], tree[2 * index + 1]);
    }

    void Update(int index, int left, int right, int position, int value) {
        int middle = (left + right) / 2;
        if (left == right) {
            tree[index] = value;
            return;
        }
        if (position <= middle)
            Update(2 * index, left, middle, position, value);
        else
            Update(2 * index + 1, middle + 1, right, position, value);
        tree[index] = max(tree[2 * index], tree[2 * index + 1]);
    }

    int Query(int index, int left, int right, int qLeft, int qRight) {
        int middle = (left + right) / 2;
        if (qLeft <= left && right <= qRight)
            return tree[index];
        int answer = -oo;
        if (qLeft <= middle)
            answer = max(answer, Query(2 * index, left, middle, qLeft, qRight));
        if (middle < qRight)
            answer = max(answer, Query(2 * index + 1, middle + 1, right, qLeft, qRight));
        return answer;
    }
};

vector<int> Tree[MAX_N];
int V, Values[MAX_N], Father[MAX_N], Level[MAX_N], Weight[MAX_N];
int Path[MAX_N], Length[MAX_N], Position[MAX_N], Begin[MAX_N];
vector<SegmentTree> SegTrees;
int Q;

void DFS(int x) {
    Weight[x] = 1;
    int heaviestSon = NIL;
    for (it y = Tree[x].begin(); y != Tree[x].end(); ++y) {
        if (*y == Father[x])
            continue;
        Father[*y] = x;
        Level[*y] = Level[x] + 1;
        DFS(*y);
        Weight[x] += Weight[*y];
        if (heaviestSon == NIL || Weight[*y] > Weight[heaviestSon])
            heaviestSon = *y;
    }
    if (heaviestSon == NIL)
        Path[x] = Path[0]++;
    else
        Path[x] = Path[heaviestSon];
    Position[x] = ++Length[Path[x]];
}

void BuildHeavyPathDecomposition() {
    Level[1] = 0;
    DFS(1);
    for (int x = 1; x <= V; ++x) {
        Position[x] = Length[Path[x]] - Position[x];
        if (Position[x] == 0)
            Begin[Path[x]] = x;
    }
}

void BuildSegmentTrees() {
    vector< vector<int> > pathValues;
    pathValues.resize(Path[0]);
    for (int p = 0; p < Path[0]; ++p)
        pathValues[p].resize(Length[p]);
    for (int x = 1; x <= V; ++x)
        pathValues[Path[x]][Position[x]] = Values[x];
    for (int p = 0; p < Path[0]; ++p)
        SegTrees.push_back(SegmentTree(pathValues[p]));
}

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

void ReadTree(ifstream &in) {
    in >> V >> Q;
    for (int x = 1; x <= V; ++x)
        in >> Values[x];
    for (int i = 1; i < V; ++i) {
        int x, y; in >> x >> y;
        Tree[x].push_back(y);
        Tree[y].push_back(x);
    }
}

int main() {
    ifstream in("heavypath.in");
    ofstream out("heavypath.out");
    ReadTree(in);
    BuildHeavyPathDecomposition();
    BuildSegmentTrees();
    for (; Q > 0; --Q) {
        int type, x, y;
        in >> type >> x >> y;
        if (type == 0)
            SegTrees[Path[x]].Update(Position[x], y);
        if (type == 1)
            out << QueryPath(x, y) << "\n";
    }
    in.close();
    out.close();
    return 0;
}