Cod sursa(job #1969648)

Utilizator tudi98Cozma Tudor tudi98 Data 18 aprilie 2017 16:14:19
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.79 kb
#include <bits/stdc++.h>
using namespace std;

#define REP(i,a) for (int i = 0; i < a; i++)
#define FOR(i,a,b) for (int i = a; i <= b; i++)
#define ROF(i,a,b) for (int i = a; i >= b; i--)
#define FOREACH(it,x) for (auto it: (x))
#define pb push_back
#define SZ(x) ((int)(x).size())

const int Nmax = 100000;

int n,m;
int weight[Nmax+1];
int data[Nmax*2+5];
int val[Nmax+1];
vector<int> G[Nmax+1];
vector< vector<int> > chain;
int what_chain[Nmax+1];
int pos_in_chain[Nmax+1];
int pos_in_aint[Nmax+1];
int T[Nmax+1];
int lvl[Nmax+1];

void dfs(int node,int parent)
{
    weight[node] = 1;
    int best = -1;
    FOREACH(it,G[node]) if (it != parent) {
        lvl[it] = lvl[node] + 1; T[it] = node;  dfs(it,node);
        weight[node] += weight[it];
        if (best == -1 || weight[best] < weight[it]) best = it;
    }
    if (best == -1) {
        chain.pb(vector<int>());
        chain.back().pb(node);
        what_chain[node] = SZ(chain) - 1;
        pos_in_chain[node] = 0;
    }
    else {
        chain[what_chain[best]].pb(node);
        what_chain[node] = what_chain[best];
        pos_in_chain[node] = SZ(chain[what_chain[best]]) - 1;
    }
}

void buildTree() {
    for (int p = n - 1; p > 0; p--)
        data[p] = max(data[p<<1],data[p<<1|1]);
}

void update(int pos,int value) {
    pos += n; data[pos] = value;
    for (; pos > 1; pos >>= 1)
        data[pos>>1] = max(data[pos],data[pos^1]);
}

int query(int l,int r) {
    int ret = 0;
    for (l += n, r += n + 1; l < r; l >>= 1, r >>= 1) {
        if (l&1)
            ret = max(ret,data[l++]);
        if (r&1)
            ret = max(ret,data[--r]);
    }
    return ret;
}

void buildHPD()
{
    lvl[1] = 0;
    dfs(1,-1);
    int cpos = 0;
    REP(i,SZ(chain)) {
        REP(j,SZ(chain[i])) {
            pos_in_aint[chain[i][j]] = cpos;
            data[cpos+n] = val[chain[i][j]];
            ++cpos;
        }
    }
    buildTree();
}

int QueryHPD(int x,int y)
{
    int ret = 0;
    while (what_chain[x] != what_chain[y]) {
        if (lvl[chain[what_chain[x]].back()] < lvl[chain[what_chain[y]].back()]) swap(x,y);
        ret = max(ret,query(pos_in_aint[x],pos_in_aint[chain[what_chain[x]].back()]));
        x = T[chain[what_chain[x]].back()];
    }
    if (pos_in_aint[x] > pos_in_aint[y]) swap(x,y);
    return max(ret,query(pos_in_aint[x],pos_in_aint[y]));
}

int main()
{
    ifstream fin("heavypath.in");
    ofstream fout("heavypath.out");

    fin >> n >> m;
    FOR(i,1,n) fin >> val[i];
    FOR(i,1,n-1) {
        int x,y;
        fin >> x >> y;
        G[x].pb(y),G[y].pb(x);
    }
    buildHPD();
    FOR(i,1,m) {
        int t,x,y; fin >> t >> x >> y;
        if (t == 0) update(pos_in_aint[x],y);
        else fout << QueryHPD(x,y) << "\n";
    }
}