Cod sursa(job #2066455)

Utilizator flaviu_2001Craciun Ioan-Flaviu flaviu_2001 Data 15 noiembrie 2017 00:50:56
Problema Heavy Path Decomposition Scor 40
Compilator cpp Status done
Runda Arhiva educationala Marime 4.62 kb
#include <bits/stdc++.h>

using namespace std;

struct thing{
    int x, d;
};

int n, test, p, depth[100005], tt[100005], euclid[200005], first_pos[100005], lg2[200005], vl[100005], subtree[100005], carelant[100005], poslant[100005];
thing pd[20][200005];
bool ok[100005];
vector<int> v[100005], lnt[100005], arb[100005];

thing min(thing a, thing b)
{
    if(a.d < b.d)
        return a;
    return b;
}

thing make_thing(int x, int d)
{
    thing aux;
    aux.x = x;
    aux.d = d;
    return aux;
}

void dfs (int x, int pred = 0)
{
    tt[x] = pred;
    ok[x] = 1;
    depth[x] = depth[tt[x]]+1;
    ++p;
    euclid[p] = x;
    first_pos[x] = p;
    subtree[x] = 1;
    for (vector<int>::iterator it = v[x].begin(); it != v[x].end(); ++it)
        if(!ok[*it]){
            dfs(*it, x);
            euclid[++p] = x;
            subtree[x] += subtree[*it];
        }
}

void build_rmq()
{
    for (int i = 1; i < p; ++i){
        pd[0][i] = make_thing(euclid[i], depth[euclid[i]]);
        if(depth[euclid[i]] > depth[euclid[i+1]])
            pd[0][i] = make_thing(euclid[i+1], depth[euclid[i+1]]);
    }
    for (int t = 1; t <= lg2[p-1]; ++t)
        for (int i = 1; i <= p-(1<<t); ++i)
            pd[t][i] = min(pd[t-1][i], pd[t-1][i+(1<<(t-1))]);
}

int query(int x, int y)
{
    if (x == y)
        return x;
    if(first_pos[x] > first_pos[y])
        swap(x, y);
    int sz = lg2[first_pos[y]-first_pos[x]];
    thing aux = min(pd[sz][first_pos[x]], pd[sz][first_pos[y]-(1<<sz)]);
    return aux.x;
}

void dfLanturi(int x)
{
    ok[x] = 0;
    int care = 0, mx = -1;
    for (vector<int>::iterator it = v[x].begin(); it != v[x].end(); ++it)
        if(ok[*it]){
            dfLanturi(*it);
            if(subtree[*it] > mx){
                care = *it;
                mx = subtree[*it];
            }
        }
    if(care == 0){
        ++p;
        lnt[p].push_back(x);
        poslant[x] = lnt[p].size()-1;
        carelant[x] = p;
    }else{
        lnt[carelant[care]].push_back(x);
        poslant[x] = lnt[carelant[care]].size()-1;
        carelant[x] = carelant[care];
    }
}

void build(int nod, int lo, int hi, int carearb)
{
    if(lo == hi){
        arb[carearb][nod] = vl[lnt[carearb][lo]];
        return;
    }
    int m = (lo+hi)/2;
    build(nod*2, lo, m, carearb);
    build(nod*2+1, m+1, hi, carearb);
    arb[carearb][nod] = max(arb[carearb][nod*2], arb[carearb][nod*2+1]);
}

void update(int nod, int lo, int hi, int val, int pos, int carearb)
{
    if(lo == hi){
        arb[carearb][nod] = val;
        return;
    }
    int m = (lo+hi)/2;
    if(m >= pos)
        update(nod*2, lo, m, val, pos, carearb);
    else update(nod*2+1, m+1, hi, val, pos, carearb);
    arb[carearb][nod] = max(arb[carearb][nod*2], arb[carearb][nod*2+1]);
}

int queryarb(int nod, int lo, int hi, int l, int r, int carearb)
{
    if(lo >= l && hi <= r)
        return arb[carearb][nod];
    int mx = -1, m = (lo+hi)/2;
    if(m >= l)
        mx = max(mx, queryarb(nod*2, lo, m, l, r, carearb));
    if(m < r)
        mx = max(mx, queryarb(nod*2+1, m+1, hi, l, r, carearb));
    return mx;
}

int hpd(int x, int y)
{
    if(depth[x] < depth[y])
        swap(x, y);
    int mx = -1;
    while(1)
    {
        if(carelant[x] == carelant[y]){
            if(poslant[x] > poslant[y])
                swap(x, y);
            return max(mx, queryarb(1, 0, lnt[carelant[x]].size()-1, poslant[x], poslant[y], carelant[x]));
        }
        mx = max(mx, queryarb(1, 0, lnt[carelant[x]].size()-1, poslant[x], lnt[carelant[x]].size()-1, carelant[x]));
        x = tt[lnt[carelant[x]].back()];
    }
    return 0;
}

int main()
{
    ifstream fin ("heavypath.in");
    ofstream fout ("heavypath.out");
    fin >> n >> test;
    for (int i = 1; i <= n; ++i)
        fin >> vl[i];
    for (int i = 1; i < n; ++i){
        int x, y;
        fin >> x >> y;
        v[x].push_back(y);
        v[y].push_back(x);
    }
    dfs(1);
    lg2[2] = 1;
    for (int i = 3; i < 200005; ++i)
        lg2[i] = lg2[i/2]+1;
    build_rmq();
    p = 0;
    dfLanturi(1);
    for (int i = 1; i <= p; ++i){
        arb[i].resize((lnt[i].size()+2)*4);
        build(1, 0, lnt[i].size()-1, i);
        /*for (vector<int>::iterator it = lnt[i].begin(); it != lnt[i].end(); ++it)
            cout << *it << " ";
        cout << "\n";*/
    }
    while(test--){
        int t, x, y;
        fin >> t >> x >> y;
        if(t == 0){
            vl[x] = y;
            update(1, 0, lnt[carelant[x]].size()-1, y, poslant[x], carelant[x]);
        }
        else{
            int lca = query(x, y), mx = -1;
            mx = max(hpd(x, lca), hpd(y, lca));
            fout << mx << "\n";
        }
    }
    fin.close();
    fout.close();
    return 0;
}