Cod sursa(job #2441716)

Utilizator vlad.ulmeanu30Ulmeanu Vlad vlad.ulmeanu30 Data 20 iulie 2019 20:52:20
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.69 kb
#include <bits/stdc++.h>
#define lll long long
#define pii pair<int,int>
#define pll pair<lll,lll>
#define fi first
#define se second
#define vi vector<int>
#define pb push_back
#define sz(a) (int)(a).size()
#define inf (INT_MAX/2-1)
#define infl (1LL<<61)
#define aaa system("pause");
#define dbg(x) cerr<<(#x)<<' '<<(x)<<'\n',aaa
#define dbga(x,n) cerr<<(#x)<<"[]: ";for(int _=0;_<=n;_++) cerr<<x[_]<<" ";cerr<<'\n'; aaa
#define maxn 100000

using namespace std;

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

struct nod
{
  int val, chi, chp, szs, tata, niv;///chi=chain index, chp=chain poz, szs=marime subarbore
  vi g;
};

struct lant { vi noduri, aint; };

nod v[maxn+5];
vector<lant> heavy;
bool viz[maxn+5];

void umax ( int &a, int b ) { a = max(a,b); }
void dfsh ( int from, int l )
{
  v[from].niv = l;
  viz[from] = 1;
  for (int to: v[from].g)
    if (!viz[to]) dfsh (to, l+1);
}

void dfs ( int from )
{
  viz[from] = 1;
  for (int to: v[from].g)
    if (!viz[to]) v[to].tata = from, dfs (to);
  v[from].szs = 1;
  for (int to: v[from].g) v[from].szs += v[to].szs;
  if (v[from].szs == 1)
  {
    heavy.pb(lant());
    v[from].chi = sz(heavy) - 1;
    v[from].chp = 0;
    heavy[v[from].chi].noduri.pb(from);
  }
  else
  {
    int wh = v[from].g[0];///unde se adauga nodul
    for (int to: v[from].g)
      if (v[to].szs > v[wh].szs) wh = to;
    v[from].chi = v[wh].chi;
    v[from].chp = sz(heavy[v[from].chi].noduri);
    heavy[v[from].chi].noduri.pb(from);
  }
}

void update ( int from, int p, pii itv ) ///from = nod a carui val trb updatata
{
  if (v[from].chp < itv.fi-1 || v[from].chp > itv.se-1) return;
  if (itv.fi == itv.se) { heavy[v[from].chi].aint[p] = v[from].val; return; }
  int mid = (itv.fi + itv.se) / 2;
  update (from, p*2, {itv.fi, mid});
  update (from, p*2+1, {mid+1, itv.se});
  heavy[v[from].chi].aint[p] = max(heavy[v[from].chi].aint[p*2], heavy[v[from].chi].aint[p*2+1]);
}

void preupdate ( int from ) { update (from, 1, {1, sz(heavy[v[from].chi].noduri)}); }

int q_aint;
void query ( int index, int p, pii itv, pii ok )
{
  if (ok.fi > itv.se || itv.fi > ok.se) return;
  if (itv.fi >= ok.fi && itv.se <= ok.se) { umax(q_aint, heavy[index].aint[p]); return; }
  int mid = (itv.fi + itv.se) / 2;
  query (index, p*2, {itv.fi, mid}, ok);
  query (index, p*2+1, {mid+1, itv.se}, ok);
}

int prequery ( int index, pii ok )
{
  ok.fi++; ok.se++;
  q_aint = 0;
  query (index, 1, {1, sz(heavy[index].noduri)}, ok);
  return q_aint;
}

int ind_dad_chain ( int from ) { return heavy[v[from].chi].noduri[sz(heavy[v[from].chi].noduri)-1]; }

int q_query;
void solve ( int x, int y )
{
  if (v[x].chi == v[y].chi)
  {
    int _m = v[x].chp, _M = v[y].chp;
    if (_m > _M) swap(_m, _M);
    umax(q_query, prequery(v[x].chi, {_m, _M}));
    return;
  }
  if (v[ind_dad_chain(x)].niv < v[ind_dad_chain(y)].niv) swap(x, y);
  umax(q_query, prequery(v[x].chi, {v[x].chp, v[ind_dad_chain(x)].chp}));
  solve(v[ind_dad_chain(x)].tata, y);
}

int main ()
{
  int n, t; fin >> n >> t;
  int i, a, b, op;
  for (i = 0; i < n; i++) fin >> v[i].val;
  for (i = 0; i < n-1; i++) fin >> a >> b, a--, b--, v[a].g.pb(b), v[b].g.pb(a);
  dfsh (0,0); memset (viz, 0, sizeof viz);
  dfs (0);
  for (i = 0; i < sz(heavy); i++ ) heavy[i].aint.resize(4*sz(heavy[i].noduri)+5);
  for (i = 0; i < n; i++ ) preupdate (i);
  while (t--)
  {
    fin >> op >> a >> b;
    if (op == 0)
    {
      a--;
      v[a].val = b;
      preupdate (a);
    }
    else
    {
      a--; b--; q_query = 0;
      solve (a, b);
      fout << q_query << '\n';
    }
  }
  fin.close(); fout.close();
  return 0;
}