Cod sursa(job #3232877)

Utilizator unomMirel Costel unom Data 1 iunie 2024 19:08:32
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.78 kb
#include <fstream>
#include <vector>
#include <cmath>

using namespace std;

ifstream in("heavypath.in");
ofstream out("heavypath.out");
int n, m, q, nr;
int p[100005];
vector<int> v[100005];
int viz[100005];
int w[100005];
int lant[100005];
int roof[100005];
int level[100005];
int sz[100005];
int loc[100005];
vector<int> segtree[100005];
vector<int> inv[100005];

void dfs(int node, int nivel)
{
    viz[node] = 1;
    w[node] = 1;
    level[node] = nivel;

    int wmax = -1;
    int poz = -1;

    for(auto it: v[node])
    {
        if(viz[it] == 0)
        {
            dfs(it, nivel + 1);

            w[node] += w[it];
            roof[lant[it]] = node;

            if(w[it] > wmax)
            {
                wmax = w[it];
                poz = it;
            }
        }
    }

    //out<<node<<" "<<w[node]<<'\n';

    if(wmax == -1)
    {
        nr++;
        lant[node] = nr;

        sz[nr] = 1;
        loc[node] = 1;
    }
    else
    {
        lant[node] = lant[poz];

        sz[lant[node]]++;
        loc[node] = sz[lant[node]];
    }
}

void build_segtree(int tree, int node, int left, int right)
{
    if(left == right)
    {
        segtree[tree][node] = p[inv[tree][left]];
    }
    else
    {
        int mij = (left + right) / 2;

        build_segtree(tree, 2*node, left, mij);
        build_segtree(tree, 2*node+1, mij + 1, right);

        segtree[tree][node] = max(segtree[tree][2*node], segtree[tree][2*node + 1]);
    }
}

void update_segtree(int tree, int node, int left, int right, int poz, int val)
{
    if(left == right)
    {
        segtree[tree][node] = val;
    }
    else
    {
        int mij = (left + right) / 2;

        if(poz <= mij)
        {
            update_segtree(tree, 2*node, left, mij, poz, val);
        }
        else
        {
            update_segtree(tree, 2*node+1, mij+1, right, poz, val);
        }

        segtree[tree][node] = max(segtree[tree][2*node], segtree[tree][2*node + 1]);
    }
}

int query_segtree(int tree, int node, int left, int right, int qleft, int qright)
{
    if(qleft <= left && right <= qright)
    {
        return segtree[tree][node];
    }
    else
    {
        int mij = (left + right) / 2;

        if(qright <= mij)
        {
            return query_segtree(tree, 2*node, left, mij, qleft, qright);
        }
        else if(mij + 1 <= qleft)
        {
            return query_segtree(tree, 2*node+1, mij + 1, right, qleft, qright);
        }

        return max(query_segtree(tree, 2*node, left, mij, qleft, qright), query_segtree(tree, 2*node+1, mij + 1, right, qleft, qright));
    }
}

int query(int a, int b)
{
    int x = a;
    int y = b;
    int ans = -1;

    while(1)
    {
        //cout<<x<<" "<<y<<'\n';

        if(lant[x] == lant[y])
        {
            int st = min(loc[x], loc[y]);
            int dr = max(loc[x], loc[y]);

            ans = max(ans, query_segtree(lant[y], 1, 1, sz[lant[y]], st, dr));

            break;
        }
        else
        {
            if(level[roof[lant[x]]] > level[roof[lant[y]]])
            {
                ans = max(ans, query_segtree(lant[x], 1, 1, sz[lant[x]], 1, loc[x]));

                x = roof[lant[x]];
            }
            else
            {
                ans = max(ans, query_segtree(lant[y], 1, 1, sz[lant[y]], 1, loc[y]));

                y = roof[lant[y]];
            }
        }
    }

    return ans;
}

int main()
{
    in>>n>>q;

    for(int i = 1; i<=n; i++)
    {
        in>>p[i];
    }

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

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

    dfs(1, 1);

    //le fac crescatoare
    for(int i = 1; i<=n; i++)
    {
        loc[i] = sz[lant[i]] - loc[i] + 1;
    }

    //out<<query_rmq(5, 8);

    /*out<<nr<<'\n';
    for(int i = 1; i<=n; i++)
    {
        out<<lant[i]<<" ";
    }
    out<<'\n';
    for(int i = 1; i<=nr; i++)
    {
        out<<sz[i]<<" ";
    }
    out<<'\n';
    for(int i = 1; i<=n; i++)
    {
        out<<loc[i]<<" ";
    }
    out<<'\n';
    for(int i = 1; i<=nr; i++)
    {
        out<<roof[i]<<" ";
    }*/

    for(int i = 1; i<=nr; i++)
    {
        segtree[i].resize(4 * sz[i] + 5);
        inv[i].resize(sz[i] + 5);
    }

    for(int i = 1; i<=n; i++)
    {
        inv[lant[i]][loc[i]] = i;
    }

    for(int i = 1; i<=nr; i++)
    {
        build_segtree(i, 1, 1, sz[i]);
    }

    int t;
    while(q--)
    {
        in>>t>>x>>y;

        if(t == 0)
        {
            update_segtree(lant[x], 1, 1, sz[lant[x]], loc[x], y);
        }
        else
        {
            out<<query(x, y)<<'\n';
        }
    }

    return 0;
}