Cod sursa(job #3289514)

Utilizator solicasolica solica solica Data 27 martie 2025 11:36:43
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 5.09 kb
/*
  ____   ___  _     ___ ____    _
 / ___| / _ \| |   |_ _/ ___|  / \
 \___ \| | | | |    | | |     / _ \
  ___) | |_| | |___ | | |___ / ___ \
 |____/ \___/|_____|___\____/_/   \_\

*/
#include <bits/stdc++.h>

using namespace std;

#define pb push_back
#define pii pair<int, int>

const int NMAX = 1e5 + 9;

const int MOD = 1e9 + 7;

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

#define cin fin
#define cout fout

int binpow(int n, int k)
{
    if (k == 0)
    {
        return 1;
    }
    int x = binpow(n, k / 2) % MOD;
    if (k % 2 == 0)
    {
        return x * x % MOD;
    }
    else
    {
        return x * x % MOD * n % MOD;
    }
}

int n, q, i, j;

int v[NMAX];

vector<int> g[NMAX];

int subtree_size[NMAX];

int heavyparent[NMAX];

int heavychild[NMAX];

int in[NMAX], out[NMAX], etour[NMAX * 2];

int minchaintimer[NMAX], maxchaintimer[NMAX];

int p[NMAX];

int timer;

int type, x, y;

int dpt[NMAX];

struct segment_tree
{
    int tree[NMAX * 8];
    void build(int node, int st, int dr)
    {
        if (st == dr)
        {
            tree[node] = etour[st];
        }
        else
        {
            int mij = (st + dr) / 2;
            build(node * 2, st, mij);
            build(node * 2 + 1, mij + 1, dr);
            tree[node] = max(tree[node * 2], tree[node * 2 + 1]);
        }
    }
    void update(int node, int st, int dr, int poz, int val)
    {
        if (st == dr)
        {
            tree[node] = val;
        }
        else
        {
            int mij = (st + dr) / 2;
            if (poz <= mij)
            {
                update(node * 2, st, mij, poz, val);
            }
            else
            {
                update(node * 2 + 1, mij + 1, dr, poz, val);
            }
            tree[node] = max(tree[node * 2], tree[node * 2 + 1]);
        }
    }
    int query(int node, int st, int dr, int l, int r)
    {
        if (l <= st && dr <= r)
        {
            return tree[node];
        }
        else
        {
            int mij = (st + dr) / 2;
            if (r <= mij)
            {
                return query(node * 2, st, mij, l, r);
            }
            if (l > mij)
            {
                return query(node * 2 + 1, mij + 1, dr, l, r);
            }
            return max(query(node * 2, st, mij, l, r), query(node * 2 + 1, mij + 1, dr, l, r));
        }
    }
} aint;

void find_subtree_size(int node, int depth = 0, int parent = 0)
{
    dpt[node] = depth;
    p[node] = parent;
    subtree_size[node] = 1;
    for (auto it : g[node])
    {
        if (it == parent)
        {
            continue;
        }
        find_subtree_size(it, depth + 1, node);
        subtree_size[node] += subtree_size[it];
    }
}

void dfsheavy(int node, int parent = 0)
{
    pii maxi = {0, 0};
    for (auto it : g[node])
    {
        if (it == parent)
        {
            continue;
        }
        maxi = max(maxi, {subtree_size[it], it});
    }
    heavychild[node] = maxi.second;
    if (!heavyparent[node])
    {
        heavyparent[node] = node;
    }
    heavyparent[heavychild[node]] = heavyparent[node];
    for (auto it : g[node])
    {
        if (it == parent)
        {
            continue;
        }
        dfsheavy(it, node);
    }
}

void eulertour(int node, int parent = 0)
{
    in[node] = ++timer;
    minchaintimer[heavyparent[node]] = min(minchaintimer[heavyparent[node]], timer);
    maxchaintimer[heavyparent[node]] = max(maxchaintimer[heavyparent[node]], timer);
    etour[timer] = v[node];
    if (heavychild[node])
    {
        eulertour(heavychild[node], node);
    }
    for (auto it : g[node])
    {
        if (it == parent || it == heavychild[node])
        {
            continue;
        }
        eulertour(it, node);
    }
    out[node] = ++timer;
    etour[timer] = v[node];
}

void query(int a, int b)
{
    int answer = 0;
    int op=0;
    while (1)
    {
        if (heavyparent[a] == heavyparent[b])
        {
            answer = max(answer, aint.query(1, 1, timer, min(in[a], in[b]), max(in[a], in[b])));
            break;
        }
        else
        {
            if (dpt[heavyparent[a]] > dpt[heavyparent[b]])
            {
                answer = max(answer, aint.query(1, 1, timer, in[heavyparent[a]], in[a]));
                a = p[heavyparent[a]];
            }
            else
            {
                answer = max (answer,aint.query (1,1,timer,in[heavyparent[b]],in[b]));
                b=p[heavyparent[b]];
            }
        }
    }
    cout<<answer<<'\n';
}

void run_case()
{
    cin >> n >> q;
    for (i = 1; i <= n; i++)
    {
        cin >> v[i];
    }
    for (i = 1; i < n; i++)
    {
        int a, b;
        cin >> a >> b;
        g[a].pb(b), g[b].pb(a);
    }
    find_subtree_size(1);
    dfsheavy(1);
    eulertour(1);
    aint.build(1, 1, timer);
    while (q--)
    {
        cin >> type >> x >> y;
        if (type == 0)
        {
            aint.update(1, 1, timer, in[x], y);
        }
        else
        {
            query(x, y);
        }
    }
}

signed main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(NULL), cout.tie(NULL);
    int teste;
    teste = 1;
    while (teste--)
    {
        run_case();
    }
}