Cod sursa(job #2986367)

Utilizator iraresmihaiiordache rares mihai iraresmihai Data 28 februarie 2023 13:19:28
Problema Heavy Path Decomposition Scor 10
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.05 kb
#include <iostream>
#include <vector>

#define MAXN 100000
#define LOG_MAXN 20
using namespace std;

struct node{
  int chain, posInChain, parent, heavyChild;
  int s, lvl, val;
  vector <int> neighbours;
};

node tree[MAXN];
vector <int> aint[MAXN];
vector <int> chains[MAXN];
int chainSize;

void dfs1(int pos) {
  tree[pos].s = 1;
  tree[pos].heavyChild = -1;
  for ( int v : tree[pos].neighbours ) {
    if ( tree[pos].parent != v ) {
      tree[v].parent = pos;
      tree[v].lvl = tree[pos].lvl + 1;
      dfs1(v);
      tree[pos].s += tree[v].s;
      if ( tree[pos].heavyChild == -1 || tree[tree[pos].heavyChild].s < tree[v].s ) {
        tree[pos].heavyChild = v;
      }
    }
  }
}

void dfs2(int pos, int chain) {
  chains[chain].push_back(pos);
  tree[pos].chain = chain;
  tree[pos].posInChain = chains[chain].size() - 1;

  for ( int v : tree[pos].neighbours ) {
    if ( v != tree[pos].parent ) {
      if ( v == tree[pos].heavyChild ) {
        dfs2(v, chain);
      } else {
        chainSize++;
        dfs2(v, chainSize);
      }
    }
  }
}

void initialiseAint(int aintPos) {
  int s;

  s = chains[aintPos].size() * 2;
  while ( s-- ) {
    aint[aintPos].push_back(0);
  }
}

void buildAint(int aintPos, int l, int r, int n) {
  if ( l == r ) {
    aint[aintPos][n] = tree[chains[aintPos][l]].val;
    return;
  }

  int nSt, nDr, mij;
  mij = (l + r) / 2;
  nSt = n + 1;
  nDr = n + 2 * (mij - l + 1);

  buildAint(aintPos, l, mij, nSt);
  buildAint(aintPos, mij + 1, r, nDr);

  aint[aintPos][n] = max(aint[aintPos][nSt], aint[aintPos][nDr]);
}

int queryAint(int aintPos, int qL, int qR, int l, int r, int n) {
  if ( qL <= l && r <= qR ) {
    return aint[aintPos][n];
  }

  int nSt, nDr, mij, ans;
  mij = (l + r) / 2;
  nSt = n + 1;
  nDr = n + 2 * (mij - l + 1);

  ans = 0;
  if ( qL <= mij ) {
    ans = max(ans, queryAint(aintPos, qL, qR, l, mij, nSt));
  }
  if ( mij < qR ) {
    ans = max(ans, queryAint(aintPos, qL, qR, mij + 1, r, nDr));
  }

  return ans;
}

void updateAint(int aintPos, int pos, int l, int r, int n) {
  if ( l == r ) {
    aint[aintPos][n] = tree[chains[aintPos][l]].val;
    return;
  }

  int nSt, nDr, mij;
  mij = (l + r) / 2;
  nSt = n + 1;
  nDr = n + 2 * (mij - l + 1);

  if ( pos <= mij ) {
    updateAint(aintPos, pos, l, mij, nSt);
  } else {
    updateAint(aintPos, pos, mij + 1, r, nDr);
  }

  aint[aintPos][n] = max(aint[aintPos][nSt], aint[aintPos][nDr]);
}

int mainQuery(int a, int b) {
  int ans;

  if ( tree[a].lvl < tree[b].lvl ) {
    swap(a, b);
  }

  ans = 0;
  while ( tree[a].chain != tree[b].chain ) {
    if ( tree[a].lvl < tree[b].lvl ) {
      swap(a, b);
    }

    ans = max(ans, queryAint(tree[a].chain, 0, tree[a].posInChain, 0, chains[tree[a].chain].size() - 1, 0));
    a = tree[chains[tree[a].chain][0]].parent;
  }

  if ( tree[a].lvl < tree[b].lvl ) {
    swap(a, b);
  }

  ans = max(ans, queryAint(tree[a].chain, tree[b].posInChain, tree[a].posInChain, 0, chains[tree[a].chain].size() - 1, 0));

  return ans;
}

void addEdge(int a, int b) {
  tree[a].neighbours.push_back(b);
  tree[b].neighbours.push_back(a);
}

int main() {
  FILE *fin, *fout;
  fin = fopen("heavypath.in", "r");
  fout = fopen("heavypath.out", "w");

  int n, q, i, t, a, b;

  fscanf(fin, "%d%d", &n, &q);

  for ( i = 0; i < n; i++ ) {
    fscanf(fin, "%d", &tree[i].val);
  }

  for ( i = 0; i < n - 1; i++ ) {
    fscanf(fin, "%d%d", &a, &b);
    a--;
    b--;

    addEdge(a, b);
  }

  chainSize = 0;
  dfs1(0);
  dfs2(0, chainSize);

  for ( i = 0; i <= chainSize; i++ ) {
    initialiseAint(i);
    buildAint(i, 0, chains[i].size() - 1, 0);
  }

  while ( q-- ) {
    fscanf(fin, "%d%d%d", &t, &a, &b);
    a--;

    if ( t ) {
      b--;
      fprintf(fout, "%d\n", mainQuery(a, b));
    } else {
      tree[a].val = b;
      updateAint(tree[a].chain, tree[a].posInChain, 0, chains[tree[a].chain].size() - 1, 0);
    }
  }

  fclose(fin);
  fclose(fout);

  return 0;
}