Cod sursa(job #2690364)

Utilizator SochuDarabaneanu Liviu Eugen Sochu Data 23 decembrie 2020 18:55:01
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.67 kb
#include <bits/stdc++.h>
#pragma GCC optimize ("03")
#define FastIO ios_base::sync_with_stdio(false) , cin.tie(0) , cout.tie(0)
#define FILES freopen("heavypath.in" , "r" , stdin) , freopen("heavypath.out" , "w" , stdout)
#define pb push_back

using namespace std;

const int N = 1e5 + 10;

int n , m , op , x , y;
int pos_chain[N] , height[N] , leaf[N] , parent[N] , nr[N] , a[N];
vector < int > g[N] , chain[N];

struct aib
{
    aib *l , *r;
    int maxi;

    aib()
    {
        l = r = 0;
        maxi = 0;
    }
}*T[N];

int chains = 0;

void dfs(int node)
{
    nr[node] = 1;
    int w = -1;

    for(int i = 0 ; i < g[node].size() ; i++)
        if(!height[ g[node][i] ])
        {
            height[ g[node][i] ] = height[node] + 1;
            parent[ g[node][i] ] = node;
            dfs( g[node][i] );
            nr[node] += nr[ g[node][i] ];

            if(w == -1 || nr[w] < nr[ g[node][i] ])
                w = g[node][i];
        }

    if(w == -1)
    {
        ++chains;
        chain[chains].pb(node);
        leaf[node] = chains;
        pos_chain[node] = 0;
        return;
    }

    chain[ leaf[w] ].pb(node);
    pos_chain[node] = chain[ leaf[w] ].size() - 1;
    leaf[node] = leaf[w];
}

int mx(aib *root)
{
    if(root == 0) return 0;
    else return root -> maxi;
}

void update(int l , int r , int pos , int val , aib *&root)
{
    if(l == r)
    {
        root -> maxi = val;
        return;
    }

    int mid = (l + r) / 2;

    if(pos <= mid)
    {
        if(root -> l == 0) root -> l = new aib;
        update(l , mid , pos , val , root -> l);
    }
    else
    {
        if(root -> r == 0) root -> r = new aib;
        update(mid + 1 , r , pos , val , root -> r);
    }

    root -> maxi = max(mx(root -> l) , mx(root -> r));
}

void query(int l , int r , int ql , int qr , aib *root , int &ans)
{
    if(root == 0)
        return;

    if(ql <= l && r <= qr)
        return ans = max(ans , root -> maxi) , void();

    int mid = (r + l) / 2;

    if(ql <= mid) query(l , mid , ql , qr , root -> l , ans);
    if(mid < qr) query(mid + 1 , r , ql , qr , root -> r , ans);
}

void build_aib()
{
    height[1] = 1;

    for(int i = 1 ; i <= chains ; i++)
    {
        T[i] = new aib;

        for(auto j : chain[i])
            update(0 , chain[i].size() - 1 , pos_chain[j] , a[j] , T[i]);
    }
}

signed main()
{
	#ifndef ONLINE_JUDGE
		FastIO , FILES;
	#endif

    int i;

    cin >> n >> m;

    for(i = 1 ; i <= n ; i++)
        cin >> a[i];

    for(i = 1 ; i < n ; i++)
    {
        cin >> x >> y;
        g[x].pb(y);
        g[y].pb(x);
    }

    dfs(1);
    build_aib();
    chain[0].pb(1);

    for(i = 1 ; i <= m ; i++)
    {
        cin >> op >> x >> y;

        if(op == 0)
        {
            int ch = leaf[x];
            update(0 , chain[ch].size() - 1 , pos_chain[x] , y , T[ch]);
        }
        else
        {
            int ans = 0;

            while(leaf[x] != leaf[y])
            {
                int p_chain_x = parent[ chain[ leaf[x] ].back() ];
                int p_chain_y = parent[ chain[ leaf[y] ].back() ];

                if(height[ p_chain_x ] < height[ p_chain_y ])
                    swap(x , y) , swap(p_chain_x , p_chain_y);

                query(0 , chain[ leaf[x] ].size() - 1 , pos_chain[x] , chain[ leaf[x] ].size() - 1 , T[ leaf[x] ] , ans);
                x = p_chain_x;
            }

            query(0 , chain[ leaf[x] ].size() - 1 , min(pos_chain[x] , pos_chain[y]) , max(pos_chain[x] , pos_chain[y]) , T[ leaf[x] ] , ans);
            cout << ans << '\n';
        }
    }

    return 0;
}