Cod sursa(job #2661464)

Utilizator victorzarzuZarzu Victor victorzarzu Data 22 octombrie 2020 08:20:36
Problema Heavy Path Decomposition Scor 20
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.54 kb
#include <bits/stdc++.h>
#define n_max 100000

using namespace std;
ifstream f("heavypath.in");
ofstream g("heavypath.out");
int n, m, pos, qpoz, qval;
int nivel[n_max + 5], t[n_max + 5], w[n_max + 5], heavy[n_max + 5], arb[4 * n_max + 5], lant[n_max + 5], poz[n_max + 5], val[n_max + 5];
vector<int> graf[n_max + 5];

void Read()
{
  f>>n>>m;
  for(int i = 1;i <= n;++i)
    f>>val[i];
  int x, y;
  for(int i = 1;i < n;++i)
    f>>x>>y, graf[x].push_back(y), graf[y].push_back(x);
}

void dfs(int nod, int parinte)
{
  w[nod] = 1;
  t[nod] = parinte;
  nivel[nod] = nivel[parinte] + 1;
  int maxim = 0;
  for(auto it : graf[nod])
    if(it != parinte)
      {
        dfs(it, nod);
        w[nod] += w[it];
        if(nivel[it] > maxim)
          maxim = nivel[it], heavy[nod] = it; //doar in jos => iau subarborele cu cel mai mare numar de noduri
      }
}

void build(int nod, int sus)
{
  lant[nod] = sus, poz[nod] = ++pos; //lant <=> root
  if(heavy[nod])
    build(heavy[nod], sus); //si asa cele care nu sunt in heavy raman pe langa si o sa fie actualizate mai tarziu
  for(auto it : graf[nod])
    if(it != t[nod] && it != heavy[nod])
      build(it, it); //cand ajung la un nod care e diferit de root, fac un nou lant, avand root-ul in nodul radacina al lantului
}

void update(int nod, int st, int dr, int qpoz, int qval)
{
  if(qpoz < st || qpoz > dr)
    return;
  if(st == dr)
  {
    arb[nod] = qval;
    return;
  }
  int mid = (st + dr) / 2;
  update(2 * nod, st, mid, qpoz, qval);
  update(2 * nod + 1, mid + 1, dr, qpoz, qval);
  arb[nod] = max(arb[2 * nod], arb[2 * nod + 1]);
}

int query(int nod, int st, int dr, int start, int finish)
{
  if(finish < st || start > dr || st > dr)
    return 0;
  if(start <= st && dr <= finish)
    return arb[nod];
  int mid = (st + dr) / 2;
  return max(query(2 * nod, st, mid, start, finish), query(2 * nod + 1, mid + 1, dr, start, finish));
}

int query_all(int x, int y)
{
  int ans = 0;
  while(lant[x] != lant[y])
  {
    if(nivel[lant[x]] > nivel[lant[y]]) swap(x, y);// daca nivelul nodului "sef" este mai mare (adica este mai jos)
    ans = max(ans, query(1, 1, n, poz[lant[y]], poz[y]));
    y = t[lant[y]];
  }
  if(nivel[x] > nivel[y])
    swap(x, y);
  ans = max(ans, query(1, 1, n, poz[x], poz[y]));
  return ans;
}

void Solve()
{
  dfs(1, 0);
  build(1, 1);
  for(int i = 1;i <= n;++i)
    update(1, 1, n, poz[i], val[i]);
  int t, x, y;
  for(int i = 1;i <= m;++i)
  {
    f>>t>>x>>y;
    if(!t)
      update(1, 1, n, poz[x], y);
    else
      g<<query_all(x, y)<<'\n';
  }
}

int main()
{
  Read();
  Solve();
  return 0;
}