Cod sursa(job #2416895)

Utilizator MiricaMateiMirica Matei MiricaMatei Data 28 aprilie 2019 15:09:54
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.41 kb
#include <bits/stdc++.h>

using namespace std;

const int MAXN = 100000;
const int BUFFSIZE = (1 << 17);

char buf[BUFFSIZE];

int buff;
FILE* fin;

void read_init(char *_fin) {
  fin = fopen(_fin, "r");
  buff = BUFFSIZE - 1;
}

char read_ch() {
  buff++;
  if (buff == BUFFSIZE) {
    buff = 0;
    fread(buf, 1, BUFFSIZE, fin);
  }
  return buf[buff];
}

int read_u32() {
  int nr = 0;
  char ch = read_ch();
  while (!('0' <= ch && ch <= '9') && ch != '-')
    ch = read_ch();
  int sgn = 1;
  if (ch == '-')
    sgn = -1, ch = read_ch();
  do {
    nr = nr * 10 + ch - '0';
    ch = read_ch();
  } while ('0' <= ch && ch <= '9');
  return sgn * nr;
}

int vl[MAXN + 5];
vector<int>G[MAXN + 5];
vector<int>lant[MAXN + 5];
int k;
int sz[MAXN + 5], h[MAXN + 5], cl[MAXN + 5], pos[MAXN + 5], up[MAXN + 5];

int join(int x, int y) {
  return max(x, y);
}

struct SegTree {
  int n;
  int *a;

  SegTree(int _n = 0) {
    n = _n;
    a = new int [4 * n + 5];
  }

  SegTree(int _n, vector<int>_a) {
    n = _n;
    a = new int [4 * n + 5];
    for (int i = 0; i < n; ++i)
      update(i + 1, vl[_a[i]]);
  }

  void update(int pos, int val) {
    upd(1, 1, n, pos, val);
  }

  int query(int l, int r) {
    return qry(1, 1, n, l, r);
  }

  void upd(int node, int l, int r, int pos, int val) {
    if (l == r) {
      a[node] = val;
      return ;
    }
    int mid = (l + r) / 2;
    if (pos <= mid)
      upd(2 * node, l, mid, pos, val);
    else
      upd(2 * node + 1, mid + 1, r, pos, val);
    a[node] = join(a[2 * node], a[2 * node + 1]);
  }

  int qry(int node, int l, int r, int x, int y) {
    if (l > r || y < l || r < x)
      return 0;
    if (x <= l && r <= y)
      return a[node];
    int mid = (l + r) / 2;
    return join(qry(2 * node, l, mid, x, y), qry(2 * node + 1, mid + 1, r, x, y));
  }
};

vector<SegTree>ch;

void dfs(int node, int f) {
  h[node] = h[f] + 1;
  up[node] = f;
  int w = 0;
  sz[node] = 1;
  for (auto it:G[node])
    if (it != f) {
      dfs(it, node);
      sz[node] += sz[it];
      if (sz[it] > sz[w])
        w = it;
    }
  if (w == 0) {
    w = k;
    k++;
  } else {
    w = cl[w];
  }
  cl[node] = w;
  lant[w].push_back(node);
}

void Update(int x, int y) {
  ch[cl[x]].update(pos[x], y);
}

int Query(int x, int y) {
  if (cl[x] == cl[y])
    return ch[cl[x]].query(min(pos[x], pos[y]), max(pos[x], pos[y]));
  if (h[lant[cl[x]][0]] < h[lant[cl[y]][0]])
    swap(x, y);
  return join(ch[cl[x]].query(1, pos[x]), Query(up[lant[cl[x]][0]], y));
}

int main() {
  read_init("heavypath.in");
  freopen("heavypath.in", "r", stdin);
  freopen("heavypath.out", "w", stdout);

  int n, m;
  n = read_u32();
  m = read_u32();
  for (int i = 1; i <= n; ++i)
    vl[i] = read_u32();
  for (int i = 1; i < n; ++i) {
    int x, y;
    x = read_u32();
    y = read_u32();
    G[x].push_back(y);
    G[y].push_back(x);
  }

  dfs(1, 0);

  for (int i = 0; i < k; ++i) {
    reverse(lant[i].begin(), lant[i].end());
    for (int j = 0; j < (int)(lant[i].size()); ++j)
      pos[lant[i][j]] = j + 1;
    SegTree aux((int)(lant[i].size()), lant[i]);
    ch.push_back(aux);
  }

  for (int i = 1; i <= m; ++i) {
    int t, x, y;
    t = read_u32();
    x = read_u32();
    y = read_u32();
    if (t == 0)
      Update(x, y);
    else
      printf("%d\n", Query(x, y));
  }

  return 0;
}