Cod sursa(job #2692023)

Utilizator popashtefan10Popa Stefan popashtefan10 Data 31 decembrie 2020 10:34:23
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.78 kb
#include <iostream>
#include <cstdio>
#include <vector>

using namespace std;

class InParser {

private:
  static const int BUFF_SIZE = 1 << 17;
  int cursor;
  char buff[BUFF_SIZE];
  FILE *in_file;

  char get_char() {
    if(cursor == BUFF_SIZE) {
      fread(buff, sizeof(buff[0]), BUFF_SIZE, in_file);
      cursor = 0;
    }
    return buff[cursor++];
  }

public:
  InParser(const char *filename) {
    in_file = fopen(filename, "r");
    cursor = BUFF_SIZE;
  }

  InParser & operator >> (int &nr) {
    char ch = get_char();
    while(ch < '0' || ch > '9') ch = get_char();

    nr = 0;
    while(ch >= '0' && ch <= '9') {
      nr = nr * 10 + ch - '0';
      ch = get_char();
    }

    return *this;
  }
};

class OutParser {

private:
  static const int BUFF_SIZE = 1 << 17;
  int cursor;
  char buff[BUFF_SIZE];
  FILE *out_file;

  char put_char(char ch) {
    if(cursor == BUFF_SIZE) {
      fwrite(buff, sizeof(buff[0]), BUFF_SIZE, out_file);
      cursor = 0;
    }
    buff[cursor++] = ch;
  }

public:
  OutParser(const char *filename) {
    out_file = fopen(filename, "w");
    cursor = 0;
  }

  OutParser & operator << (int nr) {
    if(!nr) {
      put_char('0');
      return *this;
    }

    int cf[10], nrcf = 0;
    while(nr) {
      cf[nrcf++] = nr % 10;
      nr /= 10;
    }
    for(int i = nrcf - 1; i >= 0; i--) put_char(cf[i] + '0');

    return *this;
  }

  OutParser & operator << (char ch) {
    put_char(ch);
    return *this;
  }
};

const int NMAX = 100000;

int n, m, aint_poz;
int val[NMAX + 5], h[NMAX + 5], aint[2 * NMAX + 5];
int path_first[NMAX + 5], path_dad[NMAX + 5], path_poz[NMAX + 5];
vector<int> v[NMAX + 5];

int dfs(int nod, int dad) {
  int cnt = 1, maxc = 0, heaviest = 0;
  h[nod] = h[dad] + 1;

  for(int i = 0; i < v[nod].size(); i++)
    if(v[nod][i] != dad) {
      int crt = dfs(v[nod][i], nod);
      if(crt > maxc) {
        heaviest = i;
        maxc = crt;
      }
      cnt += crt;
    }

  if(heaviest) swap(v[nod][0], v[nod][heaviest]);
  return cnt;
}

void decomposition(int nod, int dad, bool first) {
  aint[aint_poz] = val[nod];
  path_poz[nod] = aint_poz++;

  path_first[nod] = first ? nod : path_first[dad];
  path_dad[nod] = first ? dad : path_dad[dad];

  for(int i = 0; i < v[nod].size(); i++)
    if(v[nod][i] != dad) decomposition(v[nod][i], nod, i);
}

void build() {
  for(int i = n - 1; i; i--)
    aint[i] = max(aint[i << 1], aint[i << 1 | 1]);
}

void update(int nod, int val) {
  aint[path_poz[nod]] = val;
  for(int poz = path_poz[nod] >> 1; poz; poz >>= 1)
    aint[poz] = max(aint[poz << 1], aint[poz << 1 | 1]);
}

int query(int nod1, int nod2) {
  int ans = 0;
  if(path_poz[nod1] > path_poz[nod2]) swap(nod1, nod2);

  for(int st = path_poz[nod1], dr = path_poz[nod2]; st <= dr; st >>= 1, dr >>= 1) {
    if(st & 1)
      ans = max(ans, aint[st++]);
    if(!(dr & 1))
      ans = max(ans, aint[dr--]);
  }

  return ans;
}

int qquery(int nod1, int nod2) {
  int ans = 0;

  while(path_first[nod1] != path_first[nod2]) {
    if(h[path_first[nod1]] < h[path_first[nod2]]) swap(nod1, nod2);
    ans = max(ans, query(path_first[nod1], nod1));
    nod1 = path_dad[nod1];
  }
  ans = max(ans, query(nod1, nod2));

  return ans;
}

int main() {
  InParser in("heavypath.in");
  OutParser out("heavypath.out");
  int t, a, b;

  in >> n >> m;
  for(int i = 1; i <= n; i++) in >> val[i];
  for(int i = 1; i < n; i++) {
    in >> a >> b;
    v[a].push_back(b);
    v[b].push_back(a);
  }

  dfs(1, 0);
  aint_poz = n;
  decomposition(1, 0, true);

  build();
  while(m--) {
    in >> t >> a >> b;
    if(t)
      out << qquery(a, b) << '\n';
    else
      update(a, b);
  }

  return 0;
}