Cod sursa(job #1927820)

Utilizator cella.florescuCella Florescu cella.florescu Data 15 martie 2017 16:16:36
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.32 kb
#include <bits/stdc++.h>

using namespace std;

const int MAXN = 1e5;
const int NIL = 0;

vector <int> g[MAXN + 1], chain[MAXN + 1];
int *arbint[MAXN + 1];
int val[MAXN + 1], father[MAXN + 1], lev[MAXN + 1] = {0, 1}, weight[MAXN + 1], which_chain[MAXN + 1], chain_len[MAXN + 1], pos_in_chain[MAXN + 1];
bool seen[MAXN + 1];
int num_chains;

void decomp_dfs(int node) {
  int wmax = NIL;
  seen[node] = true;
  weight[node] = 1;
  for (auto it : g[node])
    if (seen[it] == false) {
      lev[it] = lev[node] + 1;
      father[it] = node;
      decomp_dfs(it);
      weight[node] += weight[it];
      wmax = (weight[it] > weight[wmax]) ? it : wmax;
    }
  if (wmax == NIL)
    which_chain[node] = ++num_chains;
  else
    which_chain[node] = which_chain[wmax];
  chain[which_chain[node]].push_back(node);
}

void build_arbint(int ind, int node, int l, int r) {
  if (l == r) {
    arbint[ind][node] = val[chain[ind][l - 1]];
    return;
  }
  int mid = (l + r) / 2;
  build_arbint(ind, 2 * node, l, mid);
  build_arbint(ind, 2 * node + 1, mid + 1, r);
  arbint[ind][node] = max(arbint[ind][2 * node], arbint[ind][2 * node + 1]);
}

void update(int ind, int node, int l, int r, int pos, int newv) {
  if (l == r) {
    arbint[ind][node] = newv;
    return;
  }
  int mid = (l + r) / 2;
  if (pos <= mid)
    update(ind, 2 * node, l, mid, pos, newv);
  else
    update(ind, 2 * node + 1, mid + 1, r, pos, newv);
  arbint[ind][node] = max(arbint[ind][2 * node], arbint[ind][2 * node + 1]);
}

int query(int ind, int node, int l, int r, int ql, int qr) {
  if (ql <= l && r <= qr)
    return arbint[ind][node];
  int mid = (l + r) / 2, a1 = 0, a2 = 0;
  if (ql <= mid)
    a1 = query(ind, 2 * node, l, mid, ql, qr);
  if (mid < qr)
    a2 = query(ind, 2 * node + 1, mid + 1, r, ql, qr);
  return max(a1, a2);
}

int heavy_query(int x, int y) {
  if (which_chain[x] == which_chain[y]) {
    if (pos_in_chain[x] > pos_in_chain[y])
      swap(x, y);
    return query(which_chain[x], 1, 1, chain_len[which_chain[x]], pos_in_chain[x], pos_in_chain[y]);
  }
  int ancx = father[chain[which_chain[x]][0]], ancy = father[chain[which_chain[y]][0]];
  if (lev[ancx] < lev[ancy]) {
    swap(x, y);
    swap(ancx, ancy);
  }
  return max(query(which_chain[x], 1, 1, chain_len[which_chain[x]], 1, pos_in_chain[x]), heavy_query(ancx, y));
}

int main()
{
    int n, m, t, x, y;
    ifstream fin("heavypath.in");
    fin >> n >> m;
    for (int i = 1; i <= n; ++i)
      fin >> val[i];
    for (int i = 1; i < n; ++i) {
      fin >> x >> y;
      g[x].push_back(y);
      g[y].push_back(x);
    }
    decomp_dfs(1);
    which_chain[0] = which_chain[1];
    for (int i = 1; i <= num_chains; ++i) {
      chain_len[i] = chain[i].size();
      reverse(chain[i].begin(), chain[i].end());
      for (int j = 0; j < chain_len[i]; ++j)
        pos_in_chain[chain[i][j]] = j + 1;
      arbint[i] = (int *) malloc(sizeof(int) * (4 * chain_len[i] + 1));
      build_arbint(i, 1, 1, chain_len[i]);
    }
    ofstream fout("heavypath.out");
    for (int i = 0; i < m; ++i) {
      fin >> t >> x >> y;
      if (t == 0)
        update(which_chain[x], 1, 1, chain_len[which_chain[x]], pos_in_chain[x], y);
      else
        fout << heavy_query(x, y) << '\n';
    }
    fin.close();
    fout.close();
    return 0;
}