Cod sursa(job #2192782)

Utilizator AndreiDumitrescuAndrei Dumitrescu AndreiDumitrescu Data 7 aprilie 2018 12:17:09
Problema Heavy Path Decomposition Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 5.11 kb
#include <fstream>
#include <iostream>
#include <vector>
#define inf -9999999

using namespace std;

ifstream f("heavypath.in");
ofstream g("heavypath.out");

int k;
vector<int> v[100001], val, lant[100001], arbint[100001];
int  greutate_lant[100001], viz[100001], ce_lant[100001] = {-1}, tata_lant[100001] = {-1}, adancime[100001];


int maxim(int a, int b)
{
    if(a > b)
        return a;
    else
        return b;
}

int actualizare(int nod1, int nod, int st, int dr, int poz, int ce_nod)
{
    if(st == dr)
        arbint[nod1][nod] = val[ce_nod];
    else
    {
        int mij =(st + dr) / 2;
        if(poz > mij)
            actualizare(nod1, 2 * nod + 1, mij+1, dr, poz, ce_nod);
        else
            actualizare(nod1, 2*nod, st, mij, poz, ce_nod);
        arbint[nod1][nod] = maxim(arbint[nod1][2*nod + 1], arbint[nod1][2*nod]);
    }
}
int interogare(int nod1, int nod, int st, int dr, int a, int b)
{
    if(a <= st && b >= dr)
    {
       return arbint[nod1][nod];
    }
    else
    {
        int mij =(st + dr) / 2, MaxLeft = inf, MaxRight = inf;
        if(a <= mij)
            MaxLeft = interogare(nod1, 2 * nod , st, mij, a, b);
        if(b > mij)
            MaxRight = interogare(nod1, 2*nod + 1, mij+1, dr, a, b);
        return maxim(MaxRight, MaxLeft);
    }

}

void DFS_ARBORE(int nod)
{
    viz[nod] = 1;
    int i, ok = 0;
    for(i = 0; i < v[nod].size(); i++)
    {
      if(viz[v[nod][i]] == 0)
      {
        ok = 1;
        DFS_ARBORE(v[nod][i]);
      }
    }
    if(ok == 0)
    {
      k++;
      greutate_lant[k]++;
      lant[k].push_back(nod);
      ce_lant[nod] = k;
    }
    else
    {
      int maxim = 0, care, ce, j;
      for(j = 0; j < v[nod].size(); j++)
      {
        if(greutate_lant[ce_lant[v[nod][j]]] > maxim)
        {
            maxim = greutate_lant[ce_lant[v[nod][j]]];
            care = ce_lant[v[nod][j]];
        }
      }
      lant[care].push_back(nod);
      ce_lant[nod] = care;
      greutate_lant[care]++;
      for(j = 0; j < v[nod].size(); j++)
      {
          if(care != ce_lant[v[nod][j]])
          {
              greutate_lant[care] += greutate_lant[ce_lant[v[nod][j]]];
          }
      }
      for(j = 0; j < v[nod].size(); j++)
      {
        if(greutate_lant[ce_lant[nod]] > greutate_lant[ce_lant[v[nod][j]]])
            tata_lant[ce_lant[v[nod][j]]] = nod;
      }
   }
}

void resize_arbint()
{
    for(int i = 1; i <= k; i++)
        arbint[i].resize(lant[i].size()* 4);
}

void creezArbInt()
{
    for(int i = 1 ; i <= k; i++)
    {
      for(int j = 0; j < lant[i].size(); j++)
      {
        actualizare(i, 1, 1, lant[i].size(), j+1, lant[i][j]);
      }
    }
}

void det_adancime()
{
  for(int i = 1; i <= k; i++)
  {
    int x = tata_lant[i];
    while(x != 0)
    {
      adancime[i]++;
      x = tata_lant[ce_lant[x]];
    }
  }
}

void afisare()
{
  for(int i = 1; i <= k; i++)
  {
    g << "Lant: " << i << ": ";
    for(int j = 0; j < lant[i].size(); j++)
      g << lant[i][j] << " ";
    g << "Tata_Lant: " << tata_lant[i] << " Adancime: " << adancime[i];
    g << '\n';
  }
}

int afla_poz(int cine, int care)
{
  for(int i = 0; i < lant[care].size(); i++)
    if(lant[care][i] == cine)
      return i+1;
}

int solve(int  x, int y)
{
  int poz, i, j, sol = 0, sol_act, poz1, aux;
  while(ce_lant[x] != ce_lant[y])
  {
    if(adancime[ce_lant[x]] >= adancime[ce_lant[y]])
    {
      poz = afla_poz(x, ce_lant[x]);
      sol_act = interogare(ce_lant[x], 1, 1, lant[ce_lant[x]].size(), poz,  lant[ce_lant[x]].size());
      if(sol_act > sol)
        sol = sol_act;
      if(tata_lant[ce_lant[x]] != 0)
        x = tata_lant[ce_lant[x]];
    }
    else
    {
      poz = afla_poz(y, ce_lant[y]);
      sol_act = interogare(ce_lant[y], 1, 1, lant[ce_lant[y]].size(), poz,  lant[ce_lant[y]].size());
      if(sol_act > sol)
        sol = sol_act;
      if(tata_lant[ce_lant[y]] != 0)
        y = tata_lant[ce_lant[y]];
    }
  }
  if(ce_lant[x] == ce_lant[y])
  {
      poz = afla_poz(x, ce_lant[x]);
      poz1 = afla_poz(y, ce_lant[y]);
      if(poz > poz1)
      {
        aux = poz1;
        poz1 = poz;
        poz = aux;
      }
      sol_act = interogare(ce_lant[y], 1, 1, lant[ce_lant[y]].size(), poz,  poz1);
      if(sol_act > sol)
        sol = sol_act;
  }
  return sol;
}

int main()
{
    int n, m, a, b, i, t, x, y, poz, sol, radacina;
    f >> n >> m;
    val.push_back(-1111);
    for(i = 0 ; i < n; i++)
    {
        f >> a;
        val.push_back(a);
    }
    for(i = 0 ; i < n - 1 ; i++)
    {
      f >> a >> b;
      v[a].push_back(b);
      v[b].push_back(a);
    }
    DFS_ARBORE(1);
    resize_arbint();
    creezArbInt();
    det_adancime();
    //afisare();
    for(i = 0; i < m; i++)
    {
       f >> t >> x >> y;
       if(t == 0)
       {
         val[x] = y;
         poz = afla_poz(x, ce_lant[x]);
         actualizare(ce_lant[x], 1, 1, lant[ce_lant[x]].size(), poz, x);
       }
       if(t == 1)
       {
         g << solve(x, y) << '\n';
       }
    }
}