Cod sursa(job #3173439)

Utilizator raileanu-alin-gabrielRaileanu Alin-Gabriel raileanu-alin-gabriel Data 22 noiembrie 2023 21:30:27
Problema Heavy Path Decomposition Scor 40
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.92 kb
#include <fstream>
#include <vector>
#include <set>
const int LOG=17;
const int NMAX=100005;

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

set<pair<int, int>> s;
vector <int> v[NMAX], path[NMAX];
int val[NMAX], poz[NMAX], sz[NMAX], pth[NMAX], nd[NMAX];
int niv[NMAX], in[NMAX], out[NMAX], w[NMAX], hv[NMAX];
int dp[LOG+2][NMAX], aint[4*NMAX];
int n, q, nrp, cnt;

void build(int, int, int);
void update(int, int, int, int, int);
int query(int, int, int, int, int);
void build_lca();
void dfs1(int);
bool is_anc(int, int);
int lca(int, int);
void dfs2(int, int);
void decomp();
void ord();
int query_hpd(int, int);
void update_hpd(int, int);
int qrry(int, int);

int main()
{
  int i, tip, a, b;
  fin>>n>>q;
  for(i=1; i<=n; i++) fin>>w[i];
  for(i=1; i<n; i++)
  {
    fin>>a>>b;
    v[a].push_back(b);
    v[b].push_back(a);
  }
  dfs1(1);
  build_lca();
  dfs2(1, 1);
  decomp();
  ord();
  for(i=1; i<=q; i++)
  {
    fin>>tip>>a>>b;
    if(tip==0) update_hpd(a, b);
    else fout<<query_hpd(a, b)<<'\n';
  }
  return 0;
}

void update_hpd(int nod, int val)
{
  update(1, 1, n, poz[nod], val);
}

int query_hpd(int a, int b)
{
  int maxim, lcaa;
  lcaa=lca(a, b);
  //fout<<a<<' '<<b<<' '<<lcaa<<'\n';
  if(lcaa==a) return qrry(a, b);
  if(lcaa==b) return qrry(b, a);
  maxim=max(qrry(lcaa, a), qrry(lcaa, b));
  return maxim;
}

int qrry(int a, int b)
{
  int maxim=0;
  while(true)
  {
    if(pth[a]==pth[b])
    {
      maxim=max(maxim, query(1, 1, n, poz[a], poz[b]));
      break;
    }
    else maxim=max(maxim, query(1, 1, n, poz[path[pth[b]][0]], poz[b]));
    b=dp[0][path[pth[b]][0]];
  }
  return maxim;
}

void ord()
{
  int i, nr=0;
  for(i=1; i<=nrp; i++)
  {
    for(auto j:path[i])
    {
      ++nr;
      val[nr]=w[j];
      poz[j]=nr;
    }
  }
  build(1, 1, n);
}

void decomp()
{
  int nod, cnt=0, i;
  for(auto i:s)
  {
      nd[++cnt]=i.second;
  }
  for(i=1; i<=n; i++)
  {
    if(!pth[nd[i]])
    {
      ++nrp;
      nod=nd[i];
      while(true)
      {
        //l-am adaugat in path-ul nrp
        path[nrp].push_back(nod);
        pth[nod]=nrp;
        if(pth[hv[nod]]) break;
        nod=hv[nod];
      }
    }
  }
}

void dfs2(int nod, int lvl)
{
  sz[nod]=1;
  niv[nod]=lvl;
  for(auto i:v[nod])
  {
    if(!sz[i])
    {
      dfs2(i, lvl+1);
      sz[nod]+=sz[i];
      if(sz[hv[nod]]<sz[i]) hv[nod]=i;
    }
  }
  v[nod].clear();
  s.insert(make_pair(niv[nod], nod));
}

int lca(int a, int b)
{
  int j;
  if(a==b || is_anc(a, b)) return a;
  if(is_anc(b, a)) return b;
  for(j=LOG; j>=0; j--)
  {
    if(!is_anc(dp[j][a], b) && dp[j][a]!=0)
      a=dp[j][a];
  }
  return dp[0][a];
}

bool is_anc(int a, int b)
{
  return (in[a]<=in[b] && out[b]<=out[a]);
}

void dfs1(int nod)
{
  in[nod]=++cnt;
  for(auto i:v[nod])
  {
    if(!in[i])
    {
      dp[0][i]=nod;
      dfs1(i);
    }
  }
  out[nod]=++cnt;
}

void build_lca()
{
  int i, j;
  for(j=1; j<=LOG; j++)
  {
    for(i=1; i<=n; i++)
    {
      dp[j][i]=dp[j-1][dp[j-1][i]];
    }
  }
}

void build(int nod, int st, int dr)
{
  if(st==dr)
  {
    aint[nod]=val[st];
    return;
  }
  int mij=(st+dr)/2;
  build(2*nod, st, mij);
  build(2*nod+1, mij+1, dr);
  aint[nod]=max(aint[2*nod], aint[2*nod+1]);
}

void update(int nod, int st, int dr, int poz, int val)
{
  if(st==dr)
  {
    aint[nod]=val;
    return;
  }
  int mij=(st+dr)/2;
  if(poz<=mij) update(2*nod, st, mij, poz, val);
  else update(2*nod+1, mij+1, dr, poz, val);
  aint[nod]=max(aint[2*nod], aint[2*nod+1]);
}

int query(int nod, int st, int dr, int qst, int qdr)
{
  if(st>=qst && dr<=qdr) return aint[nod];
  int mij=(st+dr)/2, maxim=0;
  if(qst<=mij) maxim=max(maxim, query(2*nod, st, mij, qst, qdr));
  if(qdr>mij) maxim=max(maxim, query(2*nod+1, mij+1, dr, qst, qdr));
  return maxim;
}