Cod sursa(job #2987073)

Utilizator Ana_22Ana Petcu Ana_22 Data 1 martie 2023 21:42:27
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 5.07 kb
#include <iostream>
#include <stdio.h>
#include <vector>
#define NMAX 100000
#define INF -1
#define LOGMAX 18

using namespace std;

int n, m;
vector<int> graph[NMAX];
int values[NMAX];

int current_poz, current_chain = 1;
int poz[NMAX], values2[NMAX];
int nochain[NMAX], head[NMAX];
int heavy[NMAX]; ///copilul nodului i care e heavy, deci toate muchiile astea sunt heavy

int depth[NMAX];
int ancestor[NMAX][LOGMAX];

int aint[2*NMAX];

void aint_build(int node, int nLeft, int nRight) {
  if (nLeft == nRight) {
    aint[node] = values2[nLeft];
    return;
  }
  int nMid, leftSon, rightSon;
  nMid = (nLeft + nRight) / 2;
  leftSon = node + 1;
  rightSon = node + 2 * (nMid - nLeft + 1);
  aint_build(leftSon, nLeft, nMid);
  aint_build(rightSon, nMid + 1, nRight);
  aint[node] = max( aint[leftSon], aint[rightSon] );
}

int aint_query(int node, int nLeft, int nRight, int qLeft, int qRight) {
  if (qLeft <= nLeft && qRight >= nRight)
    return aint[node];
  int nMid, leftSon, rightSon;
  int result;
  nMid = (nLeft + nRight) / 2;
  leftSon = node + 1;
  rightSon = node + 2 * (nMid - nLeft + 1);
  result = 0;
  if (qLeft <= nMid)
    result = max( result, aint_query(leftSon, nLeft, nMid, qLeft, qRight) );
  if (nMid < qRight)
    result = max( result,aint_query(rightSon, nMid + 1, nRight, qLeft, qRight) );
  return result;
}

void aint_update(int node, int nLeft, int nRight, int pos, int value) {
  if (nLeft == nRight) {
    aint[node] = value;
    return;
  }
  int nMid, leftSon, rightSon;
  nMid = (nLeft + nRight) / 2;
  leftSon = node + 1;
  rightSon = node + 2 * (nMid - nLeft + 1);
  if (pos <= nMid)
    aint_update(leftSon, nLeft, nMid, pos, value);
  else
    aint_update(rightSon, nMid + 1, nRight, pos, value);
  aint[node] = max( aint[leftSon], aint[rightSon] );
}

int dfs1( int node ) {
  int maxx, dim, aux;
  maxx = 0;
  dim = 1;
  heavy[node] = -1;
  for( unsigned int i = 0; i < graph[node].size(); i++ ) {
    int b = graph[node][i];
    if( b != ancestor[node][0] ) {
      ancestor[b][0] = node;
      aux = dfs1( b );
      if( aux > maxx ) {
        maxx = aux;
        heavy[node] = b;
      }
      dim += aux;
    }
  }
  return dim;
}

void binary_construction( int node ) {
  int i;
  for( int b : graph[node] ) {
    if( b != ancestor[node][0] ) {
      depth[b] = depth[node] + 1;
      ancestor[b][0] = node;
      for( i = 1; i < LOGMAX; i++ )
        ancestor[b][i] = ancestor[ancestor[b][i-1]][i-1];
      binary_construction( b );
    }
  }
}

int lca( int a, int b ) {
  int i;
  if( depth[a] < depth[b] )
    swap( a, b );
  int delta = depth[a] - depth[b];
  for( i = LOGMAX - 1; i >= 0; i-- )
    if( delta & ( 1 << i ) )
      a = ancestor[a][i];
  if( a == b )
    return a;
  for( i = LOGMAX - 1; i >= 0; i-- ) {
    if( ancestor[a][i] != ancestor[b][i] ) {
      a = ancestor[a][i];
      b = ancestor[b][i];
    }
  }
  return ancestor[a][0];
}

void decompose( int node ) {
  unsigned int i;
  int b;
  poz[node] = current_poz;
  current_poz++;
  values2[poz[node]] = values[node];
  nochain[node] = current_chain;
  if( heavy[node] != -1 ) {
    decompose( heavy[node] );
  }
  //printf( "%d\n", heavy[12] );
  for( i = 0; i < graph[node].size(); i++ ) {
    b = graph[node][i];
    if( b != ancestor[node][0] && b != heavy[node] ) {
      current_chain++;
      head[current_chain] = b;
      decompose( b );
    }
  }
}

int querytolca( int start, int finish ) {
  int retval = 0;
  while( nochain[start] != nochain[finish] ) {
    retval = max( retval, aint_query( 0, 0, n - 1, poz[head[nochain[start]]], poz[start] ) );
    start = ancestor[head[nochain[start]]][0];
  }
  retval = max( retval, aint_query( 0, 0, n - 1, poz[finish], poz[start] ) );
  return retval;
}

void update( int node, int val ) {
  values2[poz[node]] = val;
  aint_update( 0, 0, n - 1, poz[node], val );
}

int query( int a, int b ) {
  int x = lca( a, b );
  return max( querytolca( a, x ), querytolca( b, x ) );
}

int main() {
    FILE *fin, *fout;
    int i, a, b, cer;
    fin = fopen( "heavypath.in", "r" );
    fout = fopen( "heavypath.out", "w" );
    fscanf( fin, "%d%d", &n, &m );
    for( i = 0; i < n; i++ )
      fscanf( fin, "%d", &values[i] );
    for( i = 0; i < n - 1; i++ ) {
      fscanf( fin, "%d%d", &a, &b );
      a--, b--;
      graph[a].push_back( b );
      graph[b].push_back( a );
    }

    ancestor[0][0] = INF; ///consider radacina in nodul 0
    dfs1( 0 );
   // printf( "%d %d\n", parent[12], heavy[12] );
  //  printf( "%d %d\n", parent[33], heavy[33] );
  //  printf( "%d %d\n", parent[247], heavy[247] );
    binary_construction( 0 );
    decompose( 0 );
    aint_build( 0, 0, n - 1 );
/*
    for( i = 0; i < n; i++ )
      printf( "%d ", heavy[i] );
*/
    for( i = 0; i < m; i++ ) {
      fscanf( fin, "%d%d%d", &cer, &a, &b );
      if( cer == 0 )
        update( a - 1, b );
      else
        fprintf( fout, "%d\n", query( a - 1, b - 1 ) );
    }

    fclose( fin );
    fclose( fout );
    return 0;
}