답안 #290553

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
290553 2020-09-04T03:27:53 Z wleung_bvg 동기화 (JOI13_synchronization) C++17
100 / 100
171 ms 20844 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 N, F f) { return buildRec(0, N - 1, f); }
  void clear(Node *x) {
    if (!x) return;
    clear(x->l); deleted.push_back(x); clear(x->r);
  }
};

template <class Node> struct LCT : 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]); Node *l = TR[x].l; TR[x].l = nullptr;
    TR[x].apply(v); TR[x].propagate(); TR[x].update(); TR[x].l = l;
  }
  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> LCT(int N, F f) {
    TR.reserve(N); for (int i = 0; i < N; i++) makeNode(f());
  }
  template <class It> LCT(It st, It en) : LCT(en - st, [&] { *st++; }) {}
};

template <class T> struct NodeVal {
  using Data = T; using Lazy = Data;
  static const int RANGE_UPDATES = false, RANGE_QUERIES = false;
  static const int RANGE_REVERSALS = false, 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; }
  void reverse() {}
};

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 {};
  LCT<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 0 ms 384 KB Output is correct
2 Correct 0 ms 384 KB Output is correct
3 Correct 0 ms 384 KB Output is correct
4 Correct 0 ms 384 KB Output is correct
5 Correct 1 ms 384 KB Output is correct
6 Correct 1 ms 512 KB Output is correct
7 Correct 8 ms 1664 KB Output is correct
8 Correct 9 ms 1664 KB Output is correct
9 Correct 9 ms 1664 KB Output is correct
10 Correct 127 ms 13676 KB Output is correct
11 Correct 127 ms 13788 KB Output is correct
12 Correct 94 ms 20080 KB Output is correct
13 Correct 73 ms 13676 KB Output is correct
14 Correct 100 ms 13164 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 63 ms 16748 KB Output is correct
2 Correct 63 ms 16444 KB Output is correct
3 Correct 57 ms 19340 KB Output is correct
4 Correct 57 ms 19308 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 0 ms 384 KB Output is correct
2 Correct 0 ms 384 KB Output is correct
3 Correct 1 ms 384 KB Output is correct
4 Correct 1 ms 384 KB Output is correct
5 Correct 1 ms 384 KB Output is correct
6 Correct 2 ms 512 KB Output is correct
7 Correct 16 ms 2304 KB Output is correct
8 Correct 120 ms 20624 KB Output is correct
9 Correct 117 ms 20716 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 125 ms 20844 KB Output is correct
2 Correct 81 ms 20332 KB Output is correct
3 Correct 85 ms 20588 KB Output is correct
4 Correct 82 ms 20460 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 384 KB Output is correct
2 Correct 1 ms 384 KB Output is correct
3 Correct 0 ms 384 KB Output is correct
4 Correct 1 ms 384 KB Output is correct
5 Correct 2 ms 512 KB Output is correct
6 Correct 11 ms 1792 KB Output is correct
7 Correct 154 ms 14700 KB Output is correct
8 Correct 119 ms 20844 KB Output is correct
9 Correct 100 ms 14832 KB Output is correct
10 Correct 171 ms 14428 KB Output is correct
11 Correct 95 ms 18028 KB Output is correct
12 Correct 88 ms 17948 KB Output is correct
13 Correct 84 ms 20460 KB Output is correct