Cod sursa(job #2263644)

Utilizator pinteastefanPintea Teodor Stefan pinteastefan Data 18 octombrie 2018 22:35:25
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4 kb
#include <bits/stdc++.h>

using namespace std;
const int MAX = static_cast<const int>(1e5 + 14);
vector <int> graf[MAX];
vector <int> path[MAX];

int level[MAX], tata[MAX], sub[MAX], chain[MAX], values[MAX], poz[MAX];
int numarLanturi = 0;

vector <int> tree [MAX];

void dfs(int nod){
    sub[nod] = 1;
    for (auto x : graf[nod]){
        if (x != tata[nod]){
            tata[x]= nod;
            level[x] = level[nod] + 1;
            dfs(x);
            sub[nod] += sub[x];
        }
    }

    if(sub [nod] == 1){
        // leaf
        ++ numarLanturi;
        chain[nod] = numarLanturi;
        path[chain[nod]].push_back(nod);
        poz[nod] = path[chain[nod]].size() - 1;
    }
    else{
        int bestSon = 0;
        for (auto &son : graf [nod])
        {
            if (son != tata [nod])
            {
                if (sub [son] > sub [bestSon])
                    bestSon = son;
            }
        }
        chain[nod] = chain[bestSon];
        path[chain[nod]].push_back(nod);
        poz[nod] = path[chain[nod]].size() - 1;
    }
}

void update (vector <int> &tree, int nod, int stanga, int dreapta, const int pozitie, const int valoare){
    if (stanga == dreapta) { // in frunza
        tree[nod] = valoare;
        return;
    }
    int mij = (stanga + dreapta) >> 1;
    if (pozitie <= mij)
        update(tree, nod * 2, stanga, mij, pozitie, valoare);
    else
        update(tree, nod * 2 + 1, mij + 1, dreapta, pozitie, valoare);
    tree[nod] = max(tree[2 * nod], tree[2 * nod + 1]);
}

int getMaximum(vector<int> &tree, int nod, int stanga, int dreapta, const int a, const int b){
    if (a <= stanga and dreapta <= b){
        return tree[nod];
    }
    int mijloc = (stanga + dreapta) / 2;
    int maxim = 0;
    if (a <= mijloc){
        maxim = max(getMaximum(tree, nod * 2, stanga, mijloc, a, b), maxim);
    }
    if (mijloc < b){
        maxim = max(getMaximum(tree, nod * 2 + 1, mijloc + 1, dreapta, a, b), maxim);
    }
    return maxim;
}


int query(int x, int y){/*
    int retinut = values[x];
    while (chain[x] != chain[y]){
        if(chain[x] == chain[y]){
            retinut = max(retinut, maximDinArboreDeintervale(path[chain[y]][poz[y]],chain[x], chain[y]));
            y = x;
        }
        else{
            retinut = max(retinut, getMaximum(path[chain[y]][poz[y]], 1, chain[y]));
            y = path[chain[y]][poz[y]];
        }
    }*/
    int result = 0;
    while (chain [x] != chain[y])
    {
        if (level[tata[path[chain[x]].back()]] > level [tata[path[chain[y]].back()]])
        {
            result = max (result, getMaximum(tree[chain[x]], 1, 0, path[chain[x]].size() - 1, poz[x], path[chain[x]].size() - 1));
            x = tata[path[chain[x]].back()];
        }
        else
        {
            result = max (result, getMaximum(tree[chain[y]], 1, 0, path[chain[y]].size() - 1, poz[y], path[chain[y]].size() - 1));
            y = tata[path[chain[y]].back()];
        }
    }

    assert(chain[x] == chain[y]);

    int lo = min (poz [x], poz[y]);
    int hi = max (poz [x], poz[y]);

    return max (result, getMaximum(tree[chain[x]], 1, 0, path[chain[x]].size() - 1, lo, hi));
}

int main() {
    ifstream f("heavypath.in");
    ofstream g("heavypath.out");
    int n, m;
    f >> n >> m;
    for (int i = 1; i <= n; i++){
        f >> values[i];
    }
    for (int i = 2; i<= n; ++i){
        int a, b;
        f >> a >> b;
        graf[a].push_back(b);
        graf[b].push_back(a);
    }
    level[0] = -1;
    dfs (1);
    for (int i = 1; i <= numarLanturi; ++ i)
    {
        tree[i].resize(path[i].size() * 4);
        for (int j = 0; j < path [i].size(); ++ j) {
            assert (poz[path[i][j]] == j);
            update(tree[i], 1, 0, path[i].size() - 1, j, values[path[i][j]]);
        }
    }
    for (int i = 1; i <= m; ++i){
        int op, x, y;
        f >> op >> x >> y;
        if (op == 1)
            g << query(x, y) << '\n';
        else {
            assert(op == 0);
            update(tree[chain[x]], 1, 0, path[chain[x]].size() - 1, poz[x], y);
        }
    }
    return 0;
}