답안 #240821

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
240821 2020-06-21T08:50:02 Z wleung_bvg 동기화 (JOI13_synchronization) C++17
100 / 100
213 ms 18376 KB
#include <bits/stdc++.h>
using namespace std;
template<class C>constexpr int sz(const C&c){return int(c.size());}
using ll=long long;constexpr const char nl='\n',sp=' ';

template <class _Node, class Container = deque<_Node>> struct Splay {
  using Node = _Node; Container TR; deque<Node*> deleted;
  static_assert(Node::HAS_PAR, "Splay Node must have parent pointer");
  template <class T> Node *makeNode(const T &v) {
    if (deleted.empty()) { TR.emplace_back(v); return &TR.back(); }
    Node *x = deleted.back(); deleted.pop_back();
    *x = typename Container::value_type(v); return x;
  }
  bool isRoot(Node *x) { return !x->p || (x != x->p->l && x != x->p->r); }
  void connect(Node *x, Node *p, bool hasCh, bool isL) {
    if (x) x->p = p;
    if (hasCh) (isL ? p->l : p->r) = x;
  }
  void rotate(Node *x) {
    Node *p = x->p, *g = p->p; bool isRootP = isRoot(p), isL = x == p->l;
    connect(isL ? x->r : x->l, p, true, isL); connect(p, x, true, !isL);
    connect(x, g, !isRootP, !isRootP && p == g->l); p->update();
  }
  void splay(Node *x) {
    while (!isRoot(x)) {
      Node *p = x->p, *g = p->p; if (!isRoot(p)) g->propagate();
      p->propagate(); x->propagate();
      if (!isRoot(p)) rotate((x == p->l) == (p == g->l) ? p : x);
      rotate(x);
    }
    x->propagate(); x->update();
  }
  template <class F> void applyToRange(Node *&root, int i, int j, F f) {
    int sz = root ? root->sz : 0;
    if (i <= 0 && sz - 1 <= j) {
      f(root); if (root) { root->propagate(); root->update(); }
    } else if (i <= 0) {
      Node *l = select(root, j + 1)->l; connect(nullptr, root, true, true);
      root->update(); connect(l, nullptr, false, true); f(l);
      if (l) { l->propagate(); l->update(); }
      connect(l, root, true, true); root->update();
    } else if (sz - 1 <= j) {
      Node *r = select(root, i - 1)->r; connect(nullptr, root, true, false);
      root->update(); connect(r, nullptr, false, false); f(r);
      if (r) { r->propagate(); r->update(); }
      connect(r, root, true, false); root->update();
    } else {
      Node *r = select(root, i - 1)->r; connect(nullptr, root, true, false);
      root->update(); connect(r, nullptr, false, false);
      Node *l = select(r, j - i + 1)->l; connect(nullptr, r, true, true);
      r->update(); connect(l, nullptr, false, true); f(l);
      if (l) { l->propagate(); l->update(); }
      connect(l, r, true, true); r->update(); connect(r, root, true, false);
      root->update();
    }
  }
  Node *select(Node *&root, int k) {
    Node *last = nullptr; while (root) {
      (last = root)->propagate(); int t = root->l ? root->l->sz : 0;
      if (t > k) root = root->l;
      else if (t < k) { root = root->r; k -= t + 1; }
      else break;
    }
    if (root) splay(root);
    else if (last) splay(root = last);
    return root;
  }
  int index(Node *&root, Node *x) {
    root = x; if (!root) return -1;
    splay(root); return root->l ? root->l->sz : 0;
  }
  template <class T, class Comp>
  pair<int, Node *> getFirst(Node *&root, const T &v, Comp cmp) {
    pair<int, Node *> ret(0, nullptr); Node *last = nullptr;
    for (Node *x = root; x;) {
      (last = x)->propagate();
      if (!cmp(x->val, v)) { root = ret.second = x; x = x->l; }
      else { ret.first += 1 + (x->l ? x->l->sz : 0); x = x->r; }
    }
    if (root) splay(root);
    else if (last) splay(root = last);
    return ret;
  }
  template <class F> Node *buildRec(int l, int r, F &f) {
    if (l > r) return nullptr;
    int m = l + (r - l) / 2; Node *left = buildRec(l, m - 1, f);
    Node *ret = makeNode(f()), *right = buildRec(m + 1, r, f);
    connect(left, ret, ret, true); connect(right, ret, ret, false);
    ret->update(); return ret;
  }
  template <class F> Node *build(int l, int r, F f) {
    return buildRec(l, r, f);
  }
  void clear(Node *x) {
    if (!x) return;
    clear(x->l); deleted.push_back(x); clear(x->r);
  }
};

template <class Node> struct LinkCutTree : public Splay<Node, vector<Node>> {
  using Tree = Splay<Node, vector<Node>>;
  using Tree::TR; using Tree::makeNode; using Tree::splay; using Tree::select;
  using Data = typename Node::Data; using Lazy = typename Node::Lazy;
  int vert(Node *x) { return x - TR.data(); }
  Node *access(Node *x) {
    Node *last = nullptr;
    for (Node *y = x; y; y = y->p) { splay(y); y->r = last; last = y; }
    splay(x); return last;
  }
  template <const int _ = Node::RANGE_REVERSALS>
  typename enable_if<_>::type makeRoot(Node *x) { access(x); x->reverse(); }
  Node *findMin(Node *x) {
    for (x->propagate(); x->l; (x = x->l)->propagate());
    splay(x); return x;
  }
  Node *findMax(Node *x) {
    for (x->propagate(); x->r; (x = x->r)->propagate());
    splay(x); return x;
  }
  template <const int _ = Node::RANGE_REVERSALS>
  typename enable_if<_>::type makeRoot(int x) { makeRoot(&TR[x]); }
  int lca(int x, int y) {
    if (x == y) return x;
    access(&TR[x]); Node *ny = access(&TR[y]); return TR[x].p ? vert(ny) : -1;
  }
  bool connected(int x, int y) { return lca(x, y) != -1; }
  template <const int _ = Node::RANGE_REVERSALS>
  typename enable_if<_>::type link(int x, int y) {
    makeRoot(y); TR[y].p = &TR[x];
  }
  template <const int _ = Node::RANGE_REVERSALS>
  typename enable_if<_, bool>::type safeLink(int x, int y) {
    if (connected(x, y)) return false;
    link(x, y); return true;
  }
  bool linkParent(int par, int ch) {
    access(&TR[ch]); if (TR[ch].l) return false;
    TR[ch].p = &TR[par]; return true;
  }
  template <const int _ = Node::RANGE_REVERSALS>
  typename enable_if<_, bool>::type cut(int x, int y) {
    makeRoot(x); access(&TR[y]);
    if (&TR[x] != TR[y].l || TR[x].r) return false;
    TR[y].l->p = nullptr; TR[y].l = nullptr; return true;
  }
  bool cutParent(int x) {
    access(&TR[x]); if (!TR[x].l) return false;
    TR[x].l->p = nullptr; TR[x].l = nullptr; return true;
  }
  int findParent(int x) {
    access(&TR[x]); return TR[x].l ? vert(findMax(TR[x].l)) : -1;
  }
  int findRoot(int x) { access(&TR[x]); return vert(findMin(&TR[x])); }
  int depth(int x) { access(&TR[x]); return TR[x].l ? TR[x].l->sz : 0; }
  int kthParent(int x, int k) {
    int d = depth(x); Node *nx = &TR[x];
    return k <= d ? vert(select(nx, d - k)) : -1;
  }
  void updateVertex(int x, const Lazy &v) {
    access(&TR[x]); TR[x].apply(v); TR[x].update();
  }
  template <const int _ = Node::RANGE_UPDATES>
  typename enable_if<_>::type updatePathFromRoot(int to, const Lazy &v) {
    access(&TR[to]); TR[to].apply(v);
  }
  template <const int _ = Node::RANGE_UPDATES && Node::RANGE_REVERSALS>
  typename enable_if<_, bool>::type updatePath(
      int from, int to, const Lazy &v) {
    makeRoot(from); access(&TR[to]);
    if (from != to && !TR[from].p) return false;
    TR[to].apply(v); return true;
  }
  Data queryVertex(int x) { access(&TR[x]); return TR[x].val; }
  template <const int _ = Node::RANGE_QUERIES>
  typename enable_if<_, Data>::type queryPathFromRoot(int to) {
    access(&TR[to]); return TR[to].sbtr;
  }
  template <const int _ = Node::RANGE_QUERIES && Node::RANGE_REVERSALS>
  typename enable_if<_, Data>::type queryPath(int from, int to) {
    makeRoot(from); access(&TR[to]);
    return from == to || TR[from].p ? TR[to].sbtr : Node::qdef();
  }
  template <class F> LinkCutTree(int N, F f) {
    TR.reserve(N); for (int i = 0; i < N; i++) makeNode(f());
  }
  template <class It> LinkCutTree(It st, It en)
      : LinkCutTree(en - st, [&] { *st++; }) {}
};

template <class T> struct NodeVal {
  using Data = T;
  using Lazy = Data;
  const static int RANGE_UPDATES = false;
  const static int RANGE_QUERIES = false;
  const static int RANGE_REVERSALS = false;
  const static int HAS_PAR = true;
  int sz; NodeVal *l, *r, *p; Data val;
  NodeVal(const Data &v)
      : sz(1), l(nullptr), r(nullptr), p(nullptr), val(v) {}
  void update() {
    sz = 1;
    if (l) sz += l->sz;
    if (r) sz += r->sz;
  }
  void propagate() {}
  void apply(const Lazy &v) { val = v; }
};

int main() {
  // freopen("in.txt", "r", stdin);
  // freopen("out.txt", "w", stdout);
  // freopen("err.txt", "w", stderr);
  ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
  int N, M, Q;
  cin >> N >> M >> Q;
  vector<bool> active(N - 1, false);
  vector<vector<int>> adj(N);
  vector<pair<int, int>> E;
  vector<int> cnt(N, 1), last(N, 0);
  for (int i = 0; i < N - 1; i++) {
    int a, b;
    cin >> a >> b;
    E.emplace_back(--a, --b);
    adj[a].push_back(i);
    adj[b].push_back(i);
  }
  function<void(int, int)> dfs = [&] (int v, int prev) {
    for (int i : adj[v]) {
      if (E[i].first == prev || E[i].second == prev) continue;
      if (E[i].second == v) swap(E[i].first, E[i].second);
      dfs(E[i].second, v);
    }
  };
  dfs(0, -1);
  struct null_type {};
  LinkCutTree<NodeVal<null_type>> LCT(N, [&] { return null_type(); });
  for (int i = 0; i < M; i++) {
    int j;
    cin >> j;
    --j;
    if (active[j]) {
      last[E[j].second] = cnt[LCT.findRoot(E[j].first)];
      LCT.cutParent(E[j].second);
      cnt[E[j].second] = last[E[j].second];
    } else {
      cnt[LCT.findRoot(E[j].first)] += cnt[E[j].second] - last[E[j].second];
      LCT.linkParent(E[j].first, E[j].second);
    }
    active[j] = !active[j];
  }
  for (int i = 0; i < Q; i++) {
    int c;
    cin >> c;
    cout << cnt[LCT.findRoot(--c)] << nl;
  }
  return 0;
}
# 결과 실행 시간 메모리 Grader output
1 Correct 5 ms 384 KB Output is correct
2 Correct 5 ms 384 KB Output is correct
3 Correct 5 ms 384 KB Output is correct
4 Correct 5 ms 384 KB Output is correct
5 Correct 5 ms 384 KB Output is correct
6 Correct 6 ms 512 KB Output is correct
7 Correct 12 ms 1536 KB Output is correct
8 Correct 17 ms 1496 KB Output is correct
9 Correct 12 ms 1536 KB Output is correct
10 Correct 114 ms 11372 KB Output is correct
11 Correct 213 ms 11628 KB Output is correct
12 Correct 127 ms 17648 KB Output is correct
13 Correct 72 ms 11764 KB Output is correct
14 Correct 106 ms 11372 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 76 ms 14704 KB Output is correct
2 Correct 73 ms 14444 KB Output is correct
3 Correct 64 ms 17644 KB Output is correct
4 Correct 65 ms 17688 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 5 ms 384 KB Output is correct
2 Correct 5 ms 384 KB Output is correct
3 Correct 5 ms 384 KB Output is correct
4 Correct 5 ms 384 KB Output is correct
5 Correct 5 ms 384 KB Output is correct
6 Correct 5 ms 512 KB Output is correct
7 Correct 14 ms 2140 KB Output is correct
8 Correct 164 ms 17772 KB Output is correct
9 Correct 114 ms 17772 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 127 ms 17772 KB Output is correct
2 Correct 97 ms 18028 KB Output is correct
3 Correct 92 ms 18156 KB Output is correct
4 Correct 92 ms 18284 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 4 ms 384 KB Output is correct
2 Correct 5 ms 384 KB Output is correct
3 Correct 5 ms 384 KB Output is correct
4 Correct 5 ms 384 KB Output is correct
5 Correct 6 ms 512 KB Output is correct
6 Correct 15 ms 1536 KB Output is correct
7 Correct 139 ms 11760 KB Output is correct
8 Correct 113 ms 17772 KB Output is correct
9 Correct 97 ms 12396 KB Output is correct
10 Correct 158 ms 12140 KB Output is correct
11 Correct 97 ms 15212 KB Output is correct
12 Correct 97 ms 15212 KB Output is correct
13 Correct 95 ms 18376 KB Output is correct