Cod sursa(job #3287718)

Utilizator BOSSSTEFANPetrescu Ioan Stefan BOSSSTEFAN Data 19 martie 2025 01:05:09
Problema Heavy Path Decomposition Scor 80
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.47 kb
#include <bits/stdc++.h>

using namespace std;
const int nmax = 1e5;
int sz[nmax + 1];
vector <int> g[nmax + 1];
vector <pair <int, int>> off[nmax + 1];
struct ura
{
    int t, x, y, lca;
}q[nmax + 1];
int sef[nmax + 1], nr[nmax + 1];
int ef(int x)
{
  if(x == sef[x])
    return x;
  return sef[x] = ef(sef[x]);
}
bool ok[nmax + 1];
void dfs(int nod, int t)
{
    ok[nod] = 1;
    for(auto x : off[nod])
    {
        if(ok[x.first])
          q[x.second].lca = ef(x.first);
    }
    sz[nod] = 1;
    for(auto x : g[nod])
    {
        if(x != t)
        {
            dfs(x, nod);
            sef[x] = nod;
            sz[nod] += sz[x];
        }
    }
}
class SegmentTree
{
    private:
      int n;
      vector <int> seg;
      void pull(int nod)
      {
        int lnod = nod * 2, rnod = lnod + 1;
        seg[nod] = max(seg[lnod], seg[rnod]);
      }
      void build(int nod, int st, int dr, vector <int> &v)
      {
          if(st == dr)
          {
            seg[nod] = v[st - 1];
            return;
          }
          int mij = (st + dr) / 2, lnod = nod * 2, rnod = lnod + 1;
          build(lnod, st, mij, v);
          build(rnod, mij + 1, dr, v);
          pull(nod);
      }
      void update(int nod, int st, int dr, int poz, int val)
      {
          if(st == dr)
          {
            seg[nod] = val;
            return;
          }
          int mij = (st + dr) / 2, lnod = nod * 2, rnod = lnod + 1;
          if(poz <= mij)
            update(lnod, st, mij, poz, val);
          else
            update(rnod, mij + 1, dr, poz, val);
          pull(nod);
      }
      void query(int nod, int st, int dr, int l, int r, int &rez)
      {
          if(l <= st && dr <= r)
          {
              rez = max(rez, seg[nod]);
              return;
          }
          int mij = (st + dr) / 2, lnod = nod * 2, rnod = lnod + 1;
          if(l <= mij)
            query(lnod, st, mij, l, r, rez);
          if(r > mij)
            query(rnod, mij + 1, dr, l, r, rez);
      }
    public:
      SegmentTree(vector <int> &v)
      {
         n = v.size();
         seg.resize(n * 4 + 1);
         build(1, 1, n, v);
      }
      void upd(int poz, int val)
      {
        update(1, 1, n, poz, val);
      }
      int qry(int l, int r)
      {
          int rez = 0;
          query(1, 1, n, l, r, rez);
          return rez;
      }
      void del()
      {
          seg.clear();
      }
};
vector <SegmentTree> ab;
int t[nmax + 1], k;
struct ura2
{
    int val, l, poz;
}v[nmax + 1];
void heavy(int nod, int tt)
{
    int x = nod, y, maxi;
    v[nod].l = ++k;
    v[nod].poz = 1;
    vector <int> lant;
    lant.push_back(v[nod].val);
    t[v[nod].l] = tt;
    while(sz[x] > 1)
    {
        maxi = -1;
        for(auto z : g[x])
        {
            if(sz[z] < sz[x] && sz[z] > maxi)
            {
                maxi = sz[z];
                y = z;
            }
        }
        lant.push_back(v[y].val);
        v[y].l = v[x].l;
        v[y].poz = v[x].poz + 1;
        x = y;
    }
    SegmentTree abb(lant);
    ab.push_back(abb);
    x = nod;
    lant.clear();
    abb.del();
    while(sz[x] > 1)
    {
        for(auto z : g[x])
        {
            if(sz[z] < sz[x] && !v[z].l)
                heavy(z, x);
            else
                y = z;
        }
        x = y;
    }
}
int solve(int x, int y)
{
    if(v[x].l == v[y].l)
        return ab[v[x].l - 1].qry(v[y].poz, v[x].poz);
    else
        return max(ab[v[x].l - 1].qry(1, v[x].poz), solve(t[v[x].l], y));
}
int main()
{
    ios :: sync_with_stdio(false);
    cin.tie(0);
    freopen("heavypath.in", "r", stdin);
    freopen("heavypath.out", "w", stdout);
    int n, i, x, m, y;
    cin >> n >> m;
    for(i = 1; i <= n; i++)
    {
        sef[i] = i;
        cin >> v[i].val;
    }
    for(i = 1; i < n; i++)
    {
        cin >> x >> y;
        g[x].push_back(y);
        g[y].push_back(x);
    }
    for(i = 1; i <= m; i++)
    {
        cin >> q[i].t >> q[i].x >> q[i].y;
        if(q[i].t)
        {
           off[q[i].x].push_back({q[i].y, i});
           off[q[i].y].push_back({q[i].x, i});
        }
    }
    dfs(1, 0);
    heavy(1, 0);
    for(i = 1; i <= m; i++)
    {
        if(q[i].t)
          cout << max(solve(q[i].x, q[i].lca), solve(q[i].y, q[i].lca)) << '\n';
        else
            ab[v[q[i].x].l - 1].upd(v[q[i].x].poz, q[i].y);
    }
    return 0;
}