Cod sursa(job #2449477)

Utilizator ejoi2019Ejoi 2019 ejoi2019 Data 19 august 2019 21:27:08
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.52 kb
#include <cstdio>
#include <vector>
#include <algorithm>

using namespace std;

const int N = (int)1e5 + 7;
int n, m;
int sub[N];
vector <int> g[N];
int a[N];
bool heavy[N];
int par[N];
int dep[N];
int ids[N];
int who[N];
int pos[N];
int bg[N];

bool cmp(int i, int j) {
  return dep[i] > dep[j];
}

void dfs(int nod) {
  sub[nod] = 1;
  for (auto &nou : g[nod])
    if (sub[nou] == 0) {
      dep[nou] = 1 + dep[nod];
      dfs(nou);
      sub[nod] += sub[nou];
    } else
      par[nod] = nou;
  for (auto &nou : g[nod])
    if (nou != par[nod] && sub[nou] >= sub[nod] / 2)
      heavy[nou] = 1;
}

const int K = 19;
int euler[2 * N], top;
int first[N];
int last[N];
pair <int, int> rmq[K][2 * N];
int lg[2 * N];

void dfs_euler(int nod) {
  euler[++top] = nod;
  for (auto &nou : g[nod])
    if (nou != par[nod]) {
      dfs_euler(nou);
      euler[++top] = nod;
    }
}

int lca(int a, int b) {
  if(first[a] > last[b])
    swap(a, b);
  int i = first[a];
  int j = last[b];
  int k = lg[j - i + 1];
  return min(rmq[k][i], rmq[k][j - (1 << k) + 1]).second;
}

struct seg_tree {
  vector <int> t;
  int n;
  void init(int __n) {
    n = __n;
    t.resize(4 * n + 1);
  }

  void upd(int v, int tl, int tr, int p, int x) {
    if (tr < p || p < tl)
      return;
    if (tl == tr)
      t[v] = x;
    else {
      int tm = (tl + tr) / 2;
      upd(2 * v, tl, tm, p, x);
      upd(2 * v + 1, tm + 1, tr, p, x);
      t[v] = max(t[2 * v], t[2 * v + 1]);
    }
  }

  void upd(int p, int x) {
    upd(1, 0, n - 1, p, x);
  }

  int get(int v, int tl, int tr, int l, int r) {
    if (tr < l || r < tl)
      return -(1 << 30);
    if (l <= tl && tr <= r)
      return t[v];
    else {
      int tm = (tl + tr) / 2;
      int a = get(2 * v, tl, tm, l, r);
      int b = get(2 * v + 1, tm + 1, tr, l, r);
      return max(a, b);
    }
  }

  int get(int l, int r) {
    return get(1, 0, n - 1, l, r);
  }
};

vector <seg_tree> tt;
int hw[N];

int ask(int a, int b) {
  int c = lca(a, b);
  int ans = hw[c];
  while (1) {
    if (who[a] == who[c] || who[par[a]] == who[c]) {
      int pc = pos[c];
      int pa = pos[a];
      int wt = who[a];
      ans = max(ans, tt[wt].get(pc, pa));
      break;
    } else {
      int pa = pos[a];
      int wt = who[a];
      ans = max(ans, tt[wt].get(0, pa));
      a = par[bg[wt]];
    }
  }
  a = b;
  while (1) {
    if (who[a] == who[c] || who[par[a]] == who[c]) {
      int pc = pos[c];
      int pa = pos[a];
      int wt = who[a];
      ans = max(ans, tt[wt].get(pc, pa));
      break;
    } else {
      int pa = pos[a];
      int wt = who[a];
      ans = max(ans, tt[wt].get(0, pa));
      a = par[bg[wt]];
    }
  }
  return ans;
}

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


  for (int i = 2; i < 2 * N; i++)
    lg[i] = 1 + lg[i / 2];

  scanf("%d %d", &n, &m);
  for (int i = 1; i <= n; i++) {
    who[i] = -1;
    ids[i] = i;
    scanf("%d", &hw[i]);
  }
  for (int i = 1; i < n; i++) {
    int x, y;
    scanf("%d %d", &x, &y);
    g[x].push_back(y);
    g[y].push_back(x);
  }

  dfs(1);
  dfs_euler(1);

  for (int i = 1; i <= top; i++)
    last[euler[i]] = i;
  for (int i = top; i >= 1; i--)
    first[euler[i]] = i;

  for (int i = 1; i <= top; i++)
    rmq[0][i] = {dep[euler[i]], euler[i]};
  for (int k = 1; (1 << k) <= top; k++)
    for (int i = 1; i + (1 << k) - 1 <= top; i++)
      rmq[k][i] = min(rmq[k - 1][i], rmq[k - 1][i + (1 << (k - 1))]);

  sort(ids + 1, ids + n + 1, cmp);
  int now = -1;
  for (int j = 1; j <= n; j++) {
    int nod = ids[j];
    if (who[nod] != -1)
      continue;
    now++;
    vector <int> path;
    int cnt_light = 0;
    while (who[nod] == -1) {
      if (heavy[nod] == 0) {
        if (cnt_light == 1)
          break;
        cnt_light++;
      }
      path.push_back(nod);
      who[nod] = now;
      nod = par[nod];
    }
    reverse(path.begin(), path.end());
    bg[now] = path[0];
    int curp = -1;
    tt.push_back({});
    tt.back().init((int) path.size());
    for (auto &nod : path) {
      curp++;
      tt.back().upd(curp, hw[nod]);
      pos[nod] = curp;
    }
  }


  while (m--) {
    int qt, a, b;
    scanf("%d %d %d", &qt, &a, &b);
    if (qt == 0) {
      int wt = who[a];
      int pa = pos[a];
      hw[a] = b;
      tt[wt].upd(pa, b);
    } else {
      int ans = ask(a, b);
      printf("%d\n", ans);
    }
  }

  return 0;
}