답안 #535012

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
535012 2022-03-09T09:51:12 Z chenwz Regions (IOI09_regions) C++11
100 / 100
3920 ms 33184 KB
/* IOI 2009 "region" problem.
 *
 * Solution by Bruce Merry.
 *
 * This is the second solution described in the writeup. Briefly:
 * - queries are cached so that duplicate queries can be answered again quickly
 * - each new quality is answered in either O(A log B), O(B log A) or O(A + B),
 *   whichever is deemed fastest.
 */

#include <bits/stdc++.h>
using namespace std;
using VI = vector<int>;
using IP = pair<int, int>;
using LL = long long;

/* An employee in the tree */
struct Emp {
  int id;     /* New employee ID from a pre-order walk (0-based) */
  int reg; /* Employee's home region */
  int low;    /* Lowest ID of managees */
  int high;   /* Highest ID of managees */
  VI ch;   /* Supervisees */
};

struct Reg {
  VI ids;                /* Sorted list of (new) employee IDs */
  /* Sorted of intervals with the same nesting level. Each pair is
   * (ID, depth) where ID is the left end-point of the interval (inclusive).
   * The right end-point is implicit from the following interval.
   */
  vector<IP> ranges;
  int depth; /* Working depth during the DFS. */
  Reg() : ids(), ranges(), depth(0) {}
};

int N, R, Q;
vector<Emp> nodes;
vector<Reg> RS;

/* Does a pre-order walk over the subtree rooted at root. id_pool contains
 * the next unused employee ID, and on return it will be updated to again
 * be the next available ID.
 *
 * This procedure builds the RS arrays, after which the tree is no
 * longer needed.
 */
void dfs(int u, int &timer) {
  auto& r = RS[nodes[u].reg];
  r.ids.push_back(timer++);
  /* Depth changed, so after this point we need a new range */
  r.ranges.push_back(make_pair(timer, ++r.depth));
  for (int v : nodes[u].ch)
    dfs(v, timer);
  /* Undo the depth change, and start another interval after the last managee. */
  r.ranges.push_back(make_pair(timer, --r.depth));
}
/* Query in O(R2 log R1) time, by counting for each employee in r2. */
LL query_by_id(const Reg &r1, const Reg &r2) {
  LL ans = 0;
  for (int pos : r2.ids) {
    /* Find the first range that starts at pos or later. This will
     * actually be the range after the one we want.
     */
    auto it = lower_bound(r1.ranges.begin(), r1.ranges.end(), make_pair(pos, INT_MAX));
    if (it != r1.ranges.begin())
      ans += prev(it)->second;
  }
  return ans;
}

/* Query in O(R1 log R2) time, by counting for each employee in r1 */
LL query_by_range(const Reg &r1, const Reg &r2) {
  LL ans = 0;
  for (size_t i = 0; i + 1 < r1.ranges.size(); i++) {
    int p1 = r1.ranges[i].first, p2 = r1.ranges[i + 1].first;
    /* Each employee from r2 in [p1, p2) has depth managers
     * from r1. Find the intersections of [p1, p2) with the
     * employee list for r2.
     */
    auto first = lower_bound(r2.ids.begin(), r2.ids.end(), p1),
         last = lower_bound(r2.ids.begin(), r2.ids.end(), p2);
    ans += r1.ranges[i].second * (last - first);
  }
  return ans;
}

/* Query in O(R1 + R2) time, by counting for each employee in r1
 * but with a linear sweep instead of a binary search.
 */
LL query_stitch(const Reg &r1, const Reg &r2) {
  LL ans = 0;
  /* Find the first employee id that is in the first range */
  auto id = r2.ids.begin();
  if (r1.ranges.empty()) return ans;
  while (id != r2.ids.end() && *id < r1.ranges[0].first) id++;
  /* Iterate over the ranges as above */
  for (size_t i = 0; i + 1 < r1.ranges.size() && id != r2.ids.end(); i++) {
    /* Find the end of the section of employees from this range */
    auto id_bak = id;
    while (id != r2.ids.end() && *id < r1.ranges[i + 1].first)
      id++;
    ans += r1.ranges[i].second * (id - id_bak);
  }
  return ans;
}
LL solve(int r1, int r2) {
  map<IP, LL> cache;
  IP key(r1, r2);
  if (cache.count(key)) return cache[key];
  const Reg &reg1 = RS[r1], &reg2 = RS[r2];
  int sz1 = reg1.ids.size(), sz2 = reg2.ids.size();
  int costs[3] = {
    sz1 * ((int)log2(sz2) + 2) * 5, sz2 * ((int)log2(sz1) + 2) * 5, sz1 + sz2
  };
  // LL ans = 0;
  int k = min_element(costs, costs + 3) - costs;
  if(k == 0) return cache[key] = query_by_range(reg1, reg2);
  if(k == 1) return cache[key] = query_by_id(reg1, reg2);
  return cache[key] = query_stitch(reg1, reg2);

  // switch ()
  // {
  // case 0:
  //   ans = 
  //   break;
  // case 1:
  //   ans = 
  //   break;
  // case 2:
  //   ans = 
  //   break;
  // }
  // return cache[key] = ans;
}

int main() {
  ios::sync_with_stdio(false), cin.tie(0);
  cin >> N >> R >> Q, nodes.resize(N), RS.resize(R);
  cin >> nodes[0].reg, --nodes[0].reg;
  for (int i = 1, fa; i < N; i++) {
    cin >> fa >> nodes[i].reg;
    --fa, --nodes[i].reg, nodes[fa].ch.push_back(i);
  }
  int id_pool = 0;
  dfs(0, id_pool);
  for (int q = 0, r1, r2; q < Q; q++) {
    cin >> r1 >> r2, r1--, r2--;
    cout << solve(r1, r2) << endl;
  }
  return 0;
}
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 200 KB Output is correct
2 Correct 1 ms 200 KB Output is correct
3 Correct 2 ms 200 KB Output is correct
4 Correct 5 ms 200 KB Output is correct
5 Correct 8 ms 328 KB Output is correct
6 Correct 16 ms 328 KB Output is correct
7 Correct 25 ms 456 KB Output is correct
8 Correct 34 ms 456 KB Output is correct
9 Correct 46 ms 1096 KB Output is correct
10 Correct 71 ms 1352 KB Output is correct
11 Correct 115 ms 1864 KB Output is correct
12 Correct 119 ms 2692 KB Output is correct
13 Correct 138 ms 2584 KB Output is correct
14 Correct 149 ms 3508 KB Output is correct
15 Correct 197 ms 7016 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 2359 ms 8456 KB Output is correct
2 Correct 3920 ms 7400 KB Output is correct
3 Correct 3521 ms 11196 KB Output is correct
4 Correct 265 ms 3652 KB Output is correct
5 Correct 299 ms 5880 KB Output is correct
6 Correct 559 ms 5848 KB Output is correct
7 Correct 842 ms 7964 KB Output is correct
8 Correct 753 ms 15096 KB Output is correct
9 Correct 1273 ms 18060 KB Output is correct
10 Correct 1704 ms 24360 KB Output is correct
11 Correct 1920 ms 19788 KB Output is correct
12 Correct 1022 ms 19988 KB Output is correct
13 Correct 1217 ms 20536 KB Output is correct
14 Correct 1574 ms 20648 KB Output is correct
15 Correct 2005 ms 26296 KB Output is correct
16 Correct 1916 ms 33184 KB Output is correct
17 Correct 2628 ms 31724 KB Output is correct