제출 #1358326

#제출 시각아이디문제언어결과실행 시간메모리
1358326avighnaTourism (JOI23_tourism)C++20
0 / 100
590 ms13308 KiB
#include <bits/stdc++.h>

using namespace std;

const int inf = 1e9;

template <typename Fn1, typename Fn2>
class interval_container {
  set<pair<int, int>> st;
  map<pair<int, int>, int> mp;
  Fn1 add_fn;
  Fn2 rem_fn;

  void add(int l, int r, int x) {
    add_fn(l, r, x), mp[{l, r}] = x, st.insert({l, r});
  }

  set<pair<int, int>>::iterator rem(int l, int r) {
    rem_fn(l, r, mp[{l, r}]);
    auto it = st.find({l, r});
    return st.erase(it);
  }

  void split(int x) { // [l,r] => [l,x], [x+1,r]
    auto it = st.upper_bound({x, inf});
    if (it == st.begin()) return;
    --it;
    auto [l, r] = *it;
    if (x > r) return;
    rem(l, r);
    add(l, x, mp[{l, r}]);
    if (x + 1 <= r) add(x + 1, r, mp[{l, r}]);
  }

  void erase(int l, int r) {
    split(l - 1), split(r);
    for (auto it = st.lower_bound({l, -inf}); it != st.end() && it->second <= r;) {
      auto [l, r] = *it;
      it = rem(l, r);
    }
  }

public:
  interval_container(const Fn1 &add_fn, const Fn2 &rem_fn) : add_fn(add_fn), rem_fn(rem_fn) {}

  void insert(int l, int r, int x) {
    erase(l, r);
    add(l, r, x);
  }
};

struct query {
  int l, r, i;
};

class fenwick_tree {
  int n;
  vector<int> bit;

public:
  fenwick_tree(int _n) : n(_n), bit(_n + 1) {}

  void add(int i, int x) {
    for (i += 1; i <= n; i += i & -i) {
      bit[i] += x;
    }
  }

  int query(int i) {
    int ans = 0;
    for (i += 1; i > 0; i -= i & -i) {
      ans += bit[i];
    }
    return ans;
  }
};

template <typename Fn>
class segment_tree {
  int n;
  vector<int> seg;

  Fn merge;
  int idt;

public:
  segment_tree(int n, const Fn &merge, int idt) : merge(merge), idt(idt), n(n), seg(2 * n, idt) {}

  void set(int i, int x) {
    for (seg[i += n] = x, i >>= 1; i > 0; i >>= 1) {
      seg[i] = merge(seg[2 * i], seg[2 * i + 1]);
    }
  }

  int query(int l, int r) {
    int ans = idt;
    for (l += n, r += n + 1; l < r; l >>= 1, r >>= 1) {
      if (l & 1) ans = merge(ans, seg[l++]);
      if (r & 1) ans = merge(ans, seg[--r]);
    }
    return ans;
  }
};

int main() {
  int n, m, q;
  cin >> n >> m >> q;
  vector<vector<int>> adj(n + 1);
  for (int i = 0, u, v; i < n - 1; ++i) {
    cin >> u >> v;
    adj[u].push_back(v), adj[v].push_back(u);
  }

  vector<int> sz(n + 1);
  auto dfs_sz = [&](auto &&self, int u, int p) -> void {
    if (adj[u].size() > 1 && adj[u][0] == p) swap(adj[u][0], adj[u][1]);
    sz[u] = 1;
    for (int &i : adj[u]) {
      if (i == p) continue;
      self(self, i, u);
      sz[u] += sz[i];
      if (sz[i] > sz[adj[u][0]]) swap(i, adj[u][0]);
    }
  };
  dfs_sz(dfs_sz, 1, 0);
  vector<int> tin(n + 1), up(n + 1, 1), par(n + 1), dep(n + 1);
  int timer = 0;
  auto dfs_hld = [&](auto &&self, int u, int p) -> void {
    tin[u] = timer++;
    for (int &i : adj[u]) {
      if (i == p) continue;
      dep[i] = dep[u] + 1;
      par[i] = u;
      up[i] = i == adj[u][0] ? up[u] : i;
      self(self, i, u);
    }
  };
  dfs_hld(dfs_hld, 1, 0);
  auto get_chains_hld = [&](int u, int v) {
    vector<pair<int, int>> ans;
    while (u != v) {
      if (tin[u] < tin[v]) swap(u, v);
      if (up[u] == up[v]) {
        ans.push_back({tin[v], tin[u]});
        return ans;
      }
      ans.push_back({tin[up[u]], tin[u]});
      u = par[up[u]];
    }
    ans.push_back({tin[u], tin[u]});
    return ans;
  };
  auto lca = [&](int u, int v) {
    if (u == 0) return v;
    if (v == 0) return u;
    while (u != v) {
      if (tin[u] < tin[v]) swap(u, v);
      if (up[u] == up[v]) return v;
      u = par[up[u]];
    }
    return u;
  };

  vector<int> c(m);
  segment_tree st_lca(m, lca, 0);
  for (int i = 0; i < m; ++i) {
    cin >> c[i];
    st_lca.set(i, c[i]);
  }

  vector<query> queries(q);
  for (int i = 0, l, r; i < q; ++i) {
    cin >> l >> r;
    queries[i] = {l - 1, r - 1, i};
  }
  sort(queries.begin(), queries.end(), [&](const query &a, const query &b) { return a.l > b.l; });

  fenwick_tree cnt(n);
  auto add_fn = [&](int l, int r, int x) {
    cnt.add(x, r - l + 1);
  };
  auto rem_fn = [&](int l, int r, int x) {
    cnt.add(x, l - r - 1);
  };
  interval_container ctr(add_fn, rem_fn);

  auto add_node = [&](int u, int x) {
    for (auto &[l, r] : get_chains_hld(1, u)) {
      ctr.insert(l, r, x);
    }
  };

  int L = m;
  vector<int> ans(q);
  for (auto &[l, r, i] : queries) {
    while (L > l) {
      L--;
      add_node(c[L], L);
    }
    ans[i] = cnt.query(r) - dep[st_lca.query(l, r)];
  }

  for (int &i : ans) {
    cout << i << '\n';
  }
}
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…