제출 #1364478

#제출 시각아이디문제언어결과실행 시간메모리
1364478TraianDanciuMin-max tree (BOI18_minmaxtree)C++20
0 / 100
40 ms10172 KiB
#include <iostream>
#include <vector>

using namespace std;

const int MAXN = 70000;
const int INFINIT = 2000000000;

int minim[MAXN + 1], maxim[MAXN + 1], match[2 * MAXN + 1], aux, viz[MAXN + 1], answer[MAXN + 1], queries[MAXN + 1];
vector<int> g[MAXN + 1], gnou[MAXN + 1];

struct SegmentTree {
  struct Node {
    int minim, maxim;
  } tree[4 * MAXN];
  int n;

  void build(int node, int left, int right) {
    tree[node] = {0, INFINIT};
    if(left < right) {
      int middle = (left + right) / 2;
      build(2 * node, left, middle);
      build(2 * node + 1, middle + 1, right);
    }
  }

  void init(int n) {
    this->n = n;
    build(1, 1, n);
  }

  void updateMax(int node, int left, int right, int qleft, int qright, int val) {
    if(qleft <= left && right <= qright) {
      tree[node].maxim = min(tree[node].maxim, val);
    } else {
      int middle = (left + right) / 2;
      if(qleft <= middle) {
        updateMax(2 * node, left, middle, qleft, qright, val);
      }
      if(middle < qright) {
        updateMax(2 * node + 1, middle + 1, right, qleft, qright, val);
      }
    }
  }

  void updateMax(int st, int dr, int val) {
    updateMax(1, 1, n, st, dr, val);
  }

  void updateMin(int node, int left, int right, int qleft, int qright, int val) {
    if(qleft <= left && right <= qright) {
      tree[node].minim = max(tree[node].minim, val);
    } else {
      int middle = (left + right) / 2;
      if(qleft <= middle) {
        updateMin(2 * node, left, middle, qleft, qright, val);
      }
      if(middle < qright) {
        updateMin(2 * node + 1, middle + 1, right, qleft, qright, val);
      }
    }
  }

  void updateMin(int st, int dr, int val) {
    updateMin(1, 1, n, st, dr, val);
  }

  void dfs(int node, int left, int right, int lazymin, int lazymax) {
    lazymin = max(lazymin, tree[node].minim);
    lazymax = min(lazymax, tree[node].maxim);
    if(left == right) {
      minim[left] = lazymin;
      maxim[left] = lazymax;
    } else {
      int middle = (left + right) / 2;
      dfs(2 * node, left, middle, lazymin, lazymax);
      dfs(2 * node + 1, middle + 1, right, lazymin, lazymax);
    }
  }

  void dfs() {
    dfs(1, 1, n, 0, INFINIT);
  }
} aint;

struct HeavyLightDecomposition {
  int parent[MAXN + 1], depth[MAXN + 1], heavy[MAXN + 1], poz[MAXN + 1], head[MAXN + 1];

  int dfs(int node) {
    int sz = 1, heavy_size = 0;
    for(int son : g[node]) {
      if(son != parent[node]) {
        parent[son] = node;
        depth[son] = 1 + depth[node];
        int son_size = dfs(son);
        if(son_size > heavy_size) {
          heavy_size = son_size;
          heavy[node] = son;
        }
        sz += son_size;
      }
    }
    return sz;
  }

  void decompose(int node, int start) {
    static int timer = 0;
    poz[node] = ++timer;
    head[node] = start;
    if(heavy[node] > 0) {
      decompose(heavy[node], start);
      for(int son : g[node]) {
        if(son != parent[node] && son != heavy[node]) {
          decompose(son, son);
        }
      }
    }
  }

  void init(int n) {
    dfs(1);
    decompose(1, 1);
    aint.init(n);
  }

  void updateMax(int u, int v, int val) {
    while(head[u] != head[v]) {
      if(depth[head[u]] < depth[head[v]]) {
        swap(u, v);
      }
      aint.updateMax(poz[head[u]], poz[u], val);
      u = parent[head[u]];
    }
    if(depth[u] > depth[v]) {
      swap(u, v);
    }
    aint.updateMax(poz[u] + 1, poz[v], val);
  }

  void updateMin(int u, int v, int val) {
    while(head[u] != head[v]) {
      if(depth[head[u]] < depth[head[v]]) {
        swap(u, v);
      }
      aint.updateMin(poz[head[u]], poz[u], val);
      u = parent[head[u]];
    }
    if(depth[u] > depth[v]) {
      swap(u, v);
    }
    aint.updateMin(poz[u] + 1, poz[v], val);
  }
} hld;

bool kuhn(int u) {
  viz[u] = aux;
  for(int v : g[u]) {
    if(match[v] == 0) {
      match[u] = v;
      match[v] = u;
      return true;
    }
  }
  for(int v : g[u]) {
    if(viz[match[v]] < aux && kuhn(match[v])) {
      match[u] = v;
      match[v] = u;
      return true;
    }
  }
  return false;
}

int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);

  int n;
  cin >> n;
  for(int i = 1; i < n; i++) {
    int u, v;
    cin >> u >> v;
    g[u].push_back(v);
    g[v].push_back(u);
  }
  hld.init(n);

  int q;
  cin >> q;
  for(int i = 1; i <= q; i++) {
    char type;
    int u, v, val;
    cin >> type >> u >> v >> val;
    queries[i] = val;
    if(type == 'M') {
      hld.updateMax(u, v, val);
    } else {
      hld.updateMin(u, v, val);
    }
  }

  aint.dfs();

  for(int i = 2; i <= n; i++) {
    if(minim[hld.poz[i]] > 0) {
      gnou[minim[hld.poz[i]]].push_back(q + i);
    }
    if(maxim[hld.poz[i]] < INFINIT) {
      gnou[maxim[hld.poz[i]]].push_back(q + i);
    }
  }

  for(int i = 1; i <= q; i++) {
    aux = i;
    kuhn(i);
  }

  for(int i = 1; i <= q; i++) {
    answer[match[i] - q] = queries[i];
  }
  for(int i = 2; i <= n; i++) {
    cout << hld.parent[i] << " " << i << " ";
    if(answer[i] > 0) {
      cout << answer[i] << "\n";
    } else if(maxim[hld.poz[i]] < INFINIT) {
      cout << maxim[hld.poz[i]] << "\n";
    } else {
      cout << minim[hld.poz[i]] << "\n";
    }
  }

  return 0;
}
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…