Cod sursa(job #933395)

Utilizator a_h1926Heidelbacher Andrei a_h1926 Data 29 martie 2013 22:25:15
Problema Heavy Path Decomposition Scor 10
Compilator cpp Status done
Runda Arhiva educationala Marime 4.42 kb
#include <cstring>

#include <fstream>
#include <vector>

using namespace std;

typedef vector<int>::iterator it;

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

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

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

    int Query(int qleft, int qright) {
        return Query(1, 0, length - 1, qleft, qright);
    }

  private:
    int size, length;
    vector<int> tree;

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

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

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

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

void DFS(int X) {
    Size[X] = 1;
    int HeaviestSon = NIL;
    for (it Y = Tree[X].begin(); Y != Tree[X].end(); ++Y) {
        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)
        Path[X] = Path[0]++;
    else
        Path[X] = Path[HeaviestSon];
    Position[X] = Length[Path[X]]++;
}

void BuildHeavyPathDecomposition() {
    memset(Father, NIL, sizeof(Father));
    Father[1] = 1; Level[1] = 0;
    DFS(1);
    for (int X = 1; X <= N; ++X) {
        Position[X] = Length[Path[X]] - 1 - Position[X];
        if (Position[X] == 0)
            Begin[Path[X]] = X;
    }
}

void BuildSegmentTrees() {
    vector< vector<int> > PathValues(Path[0]);
    for (int i = 0; i < Path[0]; ++i)
        PathValues[i] = vector<int>(Length[i]);
    for (int X = 1; X <= N; ++X)
        PathValues[Path[X]][Position[X]] = Values[X];
    for (int i = 0; i < Path[0]; ++i)
        SegTrees.push_back(SegmentTree(PathValues[i]));
}

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

void Solve(ifstream& in, ofstream& out) {
    BuildHeavyPathDecomposition();
    BuildSegmentTrees();
    for (; Q > 0; --Q) {
        int Type, X, Y; in >> Type >> X >> Y;
        if (Type == 0)
            SegTrees[Path[X]].Update(Position[X], Y);
        else
            out << QueryPath(X, Y) << "\n";
    }
}

void ReadTree(ifstream& in) {
    in >> N >> Q;
    for (int i = 1; i <= N; ++i)
        in >> Values[i];
    for (int i = 1; i < N; ++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);
    Solve(in, out);
    in.close();
    out.close();
    return 0;
}