Cod sursa(job #1223707)

Utilizator a_h1926Heidelbacher Andrei a_h1926 Data 28 august 2014 17:14:24
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.29 kb
#include <cstring>

#include <fstream>
#include <algorithm>
#include <vector>

using namespace std;

const int MAX_N = 100000;
const int MAX_P = 100000;
const int MAX_SIZE = 262144;
const int NIL = -1;

vector<int> T[MAX_N];
int V, Value[MAX_N], Father[MAX_N], Size[MAX_N], Level[MAX_N];
int PathCount, Paths[MAX_N], Begin[MAX_P], End[MAX_P], PathIndex[MAX_N], PathPosition[MAX_N];
int SegmentTree[MAX_SIZE], SegmentTreeSize;

inline void UpdateSegmentTree(int where, const int value) {
    if (where < 0 || where >= SegmentTreeSize)
        return;
    SegmentTree[where += SegmentTreeSize] = value;
    for (where /= 2; where > 0; where /= 2)
        SegmentTree[where] = max(SegmentTree[2 * where], SegmentTree[2 * where + 1]);
}

inline int QuerySegmentTree(int from, int to) {
    from = max(0, from);
    to = min(SegmentTreeSize - 1, to);
    if (from > to)
        return 0;
    from += SegmentTreeSize;
    to += SegmentTreeSize;
    int maxValue = 0;
    while (from <= to) {
        maxValue = max(maxValue, max(SegmentTree[from], SegmentTree[to]));
        from = (from + 1) / 2;
        to = (to - 1) / 2;
    }
    return maxValue;
}

void HeavyDFS(const int x) {
    Size[x] = 1;
    int heaviestSon = NIL;
    for (const auto &y: T[x]) {
        if (y == Father[x])
            continue;
        Father[y] = x;
        Level[y] = Level[x] + 1;
        HeavyDFS(y);
        Size[x] += Size[y];
        if (heaviestSon == NIL || Size[y] > Size[heaviestSon])
            heaviestSon = y;
    }
    if (heaviestSon == NIL)
        PathIndex[x] = PathCount++;
    else
        PathIndex[x] = PathIndex[heaviestSon];
    ++End[PathIndex[x]];
}

void PathDFS(const int x) {
    for (const auto &y: T[x])
        if (y != Father[x])
            PathDFS(y);
    Paths[End[PathIndex[x]]] = x;
    PathPosition[x] = End[PathIndex[x]];
    ++End[PathIndex[x]];
}

void BuildSegmentTree() {
    memset(SegmentTree, 0, sizeof(SegmentTree));
    SegmentTreeSize = 1;
    for (; SegmentTreeSize < End[PathCount - 1] + 1; SegmentTreeSize *= 2);
    for (int where = 0; where < End[PathCount - 1] + 1; ++where)
        SegmentTree[where + SegmentTreeSize] = Value[Paths[where]];
    for (int where = SegmentTreeSize - 1; where > 0; --where)
        SegmentTree[where] = max(SegmentTree[2 * where], SegmentTree[2 * where + 1]);
}

void BuildHeavyPathDecomposition() {
    memset(Father, NIL, sizeof(Father));
    memset(Level, -1, sizeof(Level));
    memset(Size, 0, sizeof(Size));
    memset(Begin, 0, sizeof(Begin));
    memset(PathIndex, -1, sizeof(PathIndex));
    memset(PathPosition, -1, sizeof(PathPosition));
    Level[0] = 0;
    HeavyDFS(0);
    Begin[0] = 0;
    End[0] = End[0] - 1;
    for (int p = 1; p < PathCount; ++p) {
        Begin[p] = End[p - 1] + 1;
        End[p] = Begin[p] + End[p] - 1;
    }
    for (int p = 0; p < PathCount; ++p)
        End[p] = Begin[p];
    PathDFS(0);
    for (int p = 0; p < PathCount; ++p)
        --End[p];
    BuildSegmentTree();
}

int Query(int x, int y) {
    if (PathIndex[x] == PathIndex[y]) {
        if (PathPosition[x] > PathPosition[y])
            swap(x, y);
        return QuerySegmentTree(PathPosition[x], PathPosition[y]);
    }
    if (Level[Paths[End[PathIndex[x]]]] < Level[Paths[End[PathIndex[y]]]])
        swap(x, y);
    return max(QuerySegmentTree(PathPosition[x], End[PathIndex[x]]), Query(Father[Paths[End[PathIndex[x]]]], 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;
    for (int x = 0; x < V; ++x)
        cin >> Value[x];
    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 - 1] = value;
            UpdateSegmentTree(PathPosition[x - 1], value);
        } else {
            int x, y;
            cin >> x >> y;
            cout << Query(x - 1, y - 1) << "\n";
        }
    }
    cin.close();
    cout.close();
    return 0;
}