Cod sursa(job #2043864)

Utilizator SebiSebiPirtoaca George Sebastian SebiSebi Data 20 octombrie 2017 18:02:04
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.49 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <string.h>
using namespace std;

#define NMAX 100001
vector <int> v[NMAX];
vector <int> path[NMAX];
vector <int> arb[NMAX];
int value[NMAX], viz[NMAX], w[NMAX], niv[NMAX], p[NMAX], poz[NMAX], parent[NMAX], whatpoz[NMAX], nr_paths, q_sol;

int dfs(int nod, int lev) {
    int frunza = 1, crt = 0, fiu, sum = 0;
    viz[nod] = 1;
    niv[nod] = lev;
    for (vector <int> :: iterator it = v[nod].begin(); it != v[nod].end(); it++)
        if (viz[*it] == 0) {
            p[*it] = nod;
            int w = dfs(*it, lev + 1);
            frunza = 0;
            if (w > crt) {
                crt = w;
                fiu = *it;
            }
            sum = sum + w;
        }
    if (frunza) {
        nr_paths++;
        path[nr_paths].push_back(nod);
        poz[nod] = nr_paths;
    }
    else {
        path[poz[fiu]].push_back(nod);
        poz[nod] = poz[fiu];
    }
    return sum + 1;
}

void build(int nod, int st, int dr, int index) {
    int mij;
    if (st == dr) {
        arb[index][nod] = value[path[index][st]];
        return ;
    }
    mij = (st + dr) / 2;
    build(nod * 2, st, mij, index);
    build(nod * 2 + 1, mij + 1, dr, index);
    arb[index][nod] = max(arb[index][2 * nod], arb[index][2 * nod + 1]);
}

void update(int nod, int st, int dr, int poz, int val, int index) {
    if (st == dr) {
        arb[index][nod] = val;
        return ;
    }
    int mij = (st + dr) / 2;
    if (poz <= mij)
        update(nod * 2, st, mij, poz, val, index);
    else
        update(nod * 2 + 1, mij + 1, dr, poz, val, index);
    arb[index][nod] = max(arb[index][2 * nod], arb[index][2 * nod + 1]);
}

void query(int nod, int st, int dr, int aa, int bb, int index) {
    if (aa <= st && dr <= bb) {
        q_sol = max(q_sol, arb[index][nod]);
        return ;
    }
    int mij = (st + dr) / 2;
    if (aa <= mij)
        query(nod * 2, st, mij, aa, bb, index);
    if (mij < bb)
        query(nod * 2 + 1, mij + 1, dr, aa, bb, index);
}

void make_paths() {
    int i;
    for (i = 1; i <= nr_paths; i++) {
        reverse(path[i].begin(), path[i].end());
        for (vector <int> :: iterator it = path[i].begin(); it != path[i].end(); it++) {
            whatpoz[*it] = it - path[i].begin();
        }
        arb[i].resize(4 * path[i].size() + 1);
        build(1, 0, path[i].size() - 1, i);
        parent[i] = p[*path[i].begin()];
    }
}

int which(int x, int y) {
    if (poz[x] == poz[y]) {
        if (niv[y] < niv[x])
            swap(x, y);
        q_sol = -1;
        query(1, 0, path[poz[x]].size() - 1, whatpoz[x], whatpoz[y], poz[x]);
        return q_sol;
    }
    int px = parent[poz[x]];
    int py = parent[poz[y]];
    if (niv[py] > niv[px] || (niv[py] == niv[px] && px == 0)) {
        swap(x, y);
        swap(px, py);
    }
    q_sol = -1;
    query(1, 0, path[poz[x]].size() - 1, 0, whatpoz[x], poz[x]);
    int sol = q_sol;
    return max(sol, which(px, y));
}

int main()
{
    int n, m, x, y, i, opt;
    ifstream f("heavypath.in");
    ofstream g("heavypath.out");
    f >> n >> m;
    for (i = 1; i <= n; i++)
        f >> value[i];
    for (i = 1; i <= n - 1; i++) {
        f >> x >> y;
        v[x].push_back(y);
        v[y].push_back(x);
    }
    dfs(1, 0);
    make_paths();
    for (i = 1; i <= m; i++) {
        f >> opt >> x >> y;
        if (opt == 0) {
            update(1, 0, path[poz[x]].size() - 1, whatpoz[x], y, poz[x]);
        }
        else {
            g << which(x, y) << '\n';
        }
    }
    return 0;
}