Cod sursa(job #947804)

Utilizator mihai995mihai995 mihai995 Data 8 mai 2013 16:25:15
Problema Heavy Path Decomposition Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 4.19 kb
#include <fstream>
#include <cstring>
#include <vector>
using namespace std;

const int N = 100005, ArbCt = 5, inf = 0x3f3f3f3f;

class ArbInt{
    int arb[ArbCt * N], size;
    int x, y, val;

    inline int max(int a, int b){
        return a > b ? a : b;
    }

    inline int m(int st, int dr){
        return (st + dr) >> 1;
    }

    void update(int poz, int st, int dr){
        if (st == dr){
            arb[poz] = val;
            return;
        }

        if (x <= m(st, dr))
            update(poz << 1, st, m(st, dr));
        else
            update(1 + (poz << 1), m(st, dr) + 1, dr);

        arb[poz] = max(arb[poz << 1], arb[1 + (poz << 1)]);
    }

    void query(int poz, int st, int dr){
        if (x <= st && dr <= y){
            val = max(val, arb[poz]);
            return;
        }

        if (x <= m(st, dr))
            query(poz << 1, st, m(st, dr));

        if (m(st, dr) < y)
            query(1 + (poz << 1), 1 + m(st, dr), dr);
    }

public:
    void init(int n){
        size = n;
        memset(arb, 0, sizeof(arb));
    }

    void update(int _x, int _val){
        x = _x;
        val = _val;

        update(1, 1, size);
    }

    int query(int _x, int _y){
        x = _x;
        y = _y;
        val = -inf;

        query(1, 1, size);

        return val;
    }
};

class HeavyPath{
    int lantIndex[N], arbIndex[N], depth[N], T[N], size, nrL;
    vector<int> lant[N], *tree;
    bool use[N];
    ArbInt A;

    inline int pathSeed(int x){
        return lant[ lantIndex[x] ].back();
    }

    inline int value(int x, int y){
        return A.query(arbIndex[x], arbIndex[y]);
    }

    int heavyPath(int x){
        use[x] = true;

        int Q = 1, valPath = -1, val;

        for (vector<int> :: iterator it = tree[x].begin() ; it != tree[x].end() ; it++)
            if (!use[*it]){
                T[*it] = x;
                depth[*it] = 1 + depth[x];

                val = heavyPath(*it);
                if (val > valPath){
                    valPath = val;
                    lantIndex[x] = lantIndex[*it];
                }

                Q += val;
            }

        if (lantIndex[x] == 0)
            lantIndex[x] = ++nrL;

        lant[ lantIndex[x] ].push_back(x);

        return Q;
    }

    int lca(int x, int y){
        while (x && y && lantIndex[x] != lantIndex[y])
            if (depth[x] > depth[y])
                x = T[ pathSeed(x) ];
            else
                y = T[ pathSeed(y) ];

        if (x == 0)
            return T[ pathSeed(y) ];

        if (y == 0)
            return T[ pathSeed(x) ];
        return depth[x] > depth[y] ? x : y;
    }

    int lantQuery(int x, int L){
        int val = -inf;

        while (lantIndex[x] != lantIndex[L]){
            val = max(val, value(x, pathSeed(x)));
            x = T[ pathSeed(x) ];
        }

        return max(val, value(x, L));
    }

public:
    void buildHeavyPath(vector<int>* v, int n){
        size = n;
        tree = v;
        depth[0] = -1;

        memset(use, false, sizeof(use));
        heavyPath(1);

        for (int i = 1, j = 0 ; i <= nrL ; i++)
            for (vector<int> :: iterator it = lant[i].begin() ; it != lant[i].end() ; it++)
                arbIndex[*it] = (++j);

        A.init(n);
    }

    void update(int x, int val){
        A.update(arbIndex[x], val);
    }

    int query(int x, int y){
        int L = lca(x, y);

        return max(lantQuery(x, L), lantQuery(y, L));
    }
};

vector<int> tree[N];
HeavyPath H;
int val[N], n;

ifstream in("heavypath.in");
ofstream out("heavypath.out");

int main(){
    int nrU, t, x, y;

    in >> n >> nrU;

    for (int i = 1 ; i <= n ; i++)
        in >> val[i];

    for (int i = 1 ; i < n ; i++){
        in >> x >> y;

        tree[x].push_back(y);
        tree[y].push_back(x);
    }

    H.buildHeavyPath(tree, n);

    for (int i = 1 ; i <= n ; i++)
        H.update(i, val[i]);

    while (nrU--){
        in >> t >> x >> y;

        if (t == 0)
            H.update(x, y);
        else
            out << H.query(x, y) << "\n";
    }

    return 0;
}