Cod sursa(job #2767990)

Utilizator grecu_tudorGrecu Tudor grecu_tudor Data 8 august 2021 21:11:02
Problema Heavy Path Decomposition Scor 90
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.62 kb
#include <fstream>
#include <iostream>
#include <vector>
#include <algorithm>
 
using namespace std;
 
ifstream fin( "heavypath.in" );
ofstream fout( "heavypath.out" );
 
const int MaxN = 100002;
 
struct TreeNode {
  int val, path, pos;
} data[MaxN]; 
 
int subt[MaxN];
vector<int> T[MaxN], path[MaxN];
int viz[MaxN], dimPath[MaxN], nextNodePath[MaxN], level[MaxN];
int segT[6 * MaxN], gapPath[MaxN], gap;
 
int upos, uval;
void update( int node, int st, int dr ) {
  int mij = (st + dr) / 2;
 
  if ( st == dr ) {
    segT[node + gap] = uval;
    return;
  }
  if ( upos <= mij ) {
    update( 2 * node, st, mij );
  } else {
    update( 2 * node + 1, mij + 1, dr );
  }
  segT[node + gap] = max( segT[2 * node + gap], segT[2 * node + 1 + gap] );
}
 
int a, b;
int query( int node, int st, int dr ) {
  int mij = (st + dr) / 2, x = 0, y = 0;
 
  if ( a <= st && dr <= b ) {
    return segT[node + gap];
  }
  if ( a <= mij ) {
    x = query( 2 * node, st, mij );
  }
  if ( b > mij ) {
    y = query( 2 * node + 1, mij + 1, dr );
  }
  return max( x, y );
}
 
int calcSubT( int node ) {
  subt[node] = viz[node] = 1;
  for ( int i = 0; i < (int)T[node].size(); ++i ) {
	if ( !viz[T[node][i]] ) {
	  subt[node] += calcSubT( T[node][i] );
	}
  }
  return subt[node];
}
 
int npath;
 
void buildPaths( int node ) {
  int mxNode = -1, mx = 0, currPath;
  
  viz[node] = 1;
  for ( int i = 0; i < (int)T[node].size(); ++i ) {
	if ( !viz[T[node][i]] ) {
	  level[T[node][i]] = level[node] + 1;
      if ( subt[T[node][i]] > mx ) {
	    mx = subt[T[node][i]];
		mxNode = T[node][i];
	  }
	  buildPaths( T[node][i] );
	}
  }
  for ( int i = 0; i < (int)T[node].size(); ++i ) {
	if ( T[node][i] != mxNode ) {
	  nextNodePath[data[T[node][i]].path] = node;
	}
  }
  if ( mxNode != -1 ) { 
    currPath = data[node].path = data[mxNode].path;
    data[node].pos = data[mxNode].pos + 1;
	path[currPath].push_back( node );
	++dimPath[currPath];
  } else {
	currPath = data[node].path = npath++;
	data[node].pos = 1;
	path[currPath].push_back( node );
	++dimPath[currPath];
  }
}
 
int x, y;
 
int main() {
  int n, m, i, tp, maxXYpath;
 
  fin >> n >> m;
  for ( i = 1; i <= n; ++i ) {
	fin >> data[i].val;
  }
  for ( i = 1; i < n; ++i ) {
	fin >> x >> y;
	T[x].push_back( y );
	T[y].push_back( x );
  }
  level[1] = 1;
  calcSubT( 1 );
  for ( i = 1; i <= n; ++i ) {
    viz[i] = 0;
  }
  buildPaths( 1 );
  nextNodePath[data[1].path] = 0;
  for ( i = 0; i < npath; ++i ) {
	gapPath[i] = gapPath[i - 1] + 4 * dimPath[i - 1] + 1; 
    gap = gapPath[i] + 1;
    for ( int j = 0; j < dimPath[i]; ++j ) {
	  uval = data[path[i][j]].val, upos = data[path[i][j]].pos;
	  update( 1, 1, dimPath[i] );
	}
  }
  while ( m-- ) {
    fin >> tp >> x >> y;
	if ( tp == 0 ) { 
      upos = data[x].pos, uval = y, gap = gapPath[data[x].path] + 1;
	  update( 1, 1, dimPath[data[x].path] );
	} else { 
	  maxXYpath = 0;
	  while ( data[x].path != data[y].path ) {
		if ( level[nextNodePath[data[x].path]] > level[nextNodePath[data[y].path]] ) {
		  gap = gapPath[data[x].path] + 1, a = data[x].pos, b = dimPath[data[x].path];
          maxXYpath = max( maxXYpath, query( 1, 1, dimPath[data[x].path] ) );
	      x = nextNodePath[data[x].path];
		} else {
		  gap = gapPath[data[y].path] + 1, a = data[y].pos, b = dimPath[data[y].path];
		  maxXYpath = max( maxXYpath, query( 1, 1, dimPath[data[y].path] ) );
          y = nextNodePath[data[y].path];
		}
	  }	
	  gap = gapPath[data[x].path] + 1;
	  a = min( data[x].pos, data[y].pos );
	  b = max( data[x].pos, data[y].pos );
      maxXYpath = max( maxXYpath, query( 1, 1, dimPath[data[x].path] ) );
	  fout << maxXYpath << "\n";
	}
  }
  fin.close();
  fout.close();
  return 0;
}