제출 #500744

#제출 시각아이디문제언어결과실행 시간메모리
500744cs142857Regions (IOI09_regions)C++17
100 / 100
2971 ms29500 KiB
#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cctype>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <deque>
#include <functional>
#include <iostream>
#include <map>
#include <memory>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
using namespace std;

#ifdef DBG
  #define dbg 1
  #define dpf(...) fprintf(stderr, __VA_ARGS__);fflush(stderr);
  #define Dps(...) Dbgs(__VA_ARGS__)
#else
  #define dbg 0
  #define dpf(...) 42
  #define Dps(...) 42
#endif
 
#define SIZE(c) int((c).size())
#define FOR(i,l,r) for(int i = (l); i < (r); ++i)
#define REP(i,c) for(auto &i : (c))
#define ALL(c) (c).begin(),(c).end()
#define pb push_back
#define eb emplace_back
#define fi first
#define se second
typedef long long i64;
typedef unsigned long long u64;
const double EPS = 1e-12;
const int INF = 1e9 + 10;
typedef vector<int> VI;
typedef vector<string> VS;
typedef pair<int, int> PI;

template <typename T> inline bool UpdateMax(T& x, T v) {
  if(v > x) {x=v; return 1;} else return 0;
}
template <typename T> inline bool UpdateMin(T& x, T v) {
  if(v < x) {x=v; return 1;} else return 0;
}

template <typename T>
using MinPQ = priority_queue<T, vector<T>, greater<T>>;

inline namespace output {
template <typename T1, typename T2>
std::ostream& operator<<(std::ostream& os, const std::pair<T1, T2>& v) {
  return os << "{" << v.first << " " << v.second << "}";
}

template <typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<T>& v) {
  os << "{";
  bool first = 1;
  REP(x, v) {
    if(first) first=0; else os << " ";
    os << x;
  }
  return os << "}";
}
}  // namespace output

inline namespace output {  // Only for debug now.
template <class T>
void PrSep(std::ostream& os, string, const T& t) { os << t; }
template <class T, class... U>
void PrSep(std::ostream& os, string sep, const T& t, const U&... u) {
  PrSep(os, sep, t); os << sep; PrSep(os, sep, u...);
}

// Print w/ spaces, end with newline
void Ps() { cout << "\n"; }
template<class ...T> void Ps(const T&... t) { PrSep(cout," ",t...); Ps(); } 
template<class ...T> void Dbgs(const T&... t) { PrSep(cerr," ",t...); cerr << endl; } 
}  // namespace output

int n, m;
VI par, home; 
VI r_cnt;
int big_cnt;

vector<char> rtype;
VI rtype_cnt;
vector<int> ridx;

vector<vector<PI>> r0_subtree_dfs_range;
vector<VI> dfs_pos;

vector<VI> ans10;
vector<vector<i64>> ans11;

void Build() {
  VI start(n, -1);
  VI next_son(n, -1);
  FOR(i, 1, n) {
    next_son[i] = start[par[i]];
    start[par[i]] = i;
  }

  ans10.assign(rtype_cnt[1], VI(rtype_cnt[0], 0));
  ans11.assign(rtype_cnt[1], vector<i64>(rtype_cnt[1], 0));

  r0_subtree_dfs_range.assign(rtype_cnt[0], {});
  dfs_pos.assign(m, {});
  FOR(i, 0, m) {
    if (rtype[i] == 0) r0_subtree_dfs_range[ridx[i]].reserve(r_cnt[i]);
    dfs_pos[i].reserve(r_cnt[i]);
  }

  VI par_r1cnt(rtype_cnt[1], 0);
  VI par_r1;
  int dfsn = -1;
  const std::function<void(int)> Dfs = [&](int u) {
    dfsn++;
    int ru = home[u];
    REP(p, par_r1) {
      if (rtype[ru] == 0) {
        ans10[ridx[p]][ridx[ru]] += par_r1cnt[ridx[p]];
      } else {
        ans11[ridx[p]][ridx[ru]] += par_r1cnt[ridx[p]];
      }
    }
    if (rtype[ru] == 1) {
      if (par_r1cnt[ridx[ru]]++ == 0) par_r1.pb(ru);
    }
    dfs_pos[ru].pb(dfsn);

    int dfs_l = dfsn + 1;
    for (int v = start[u]; v >= 0; v = next_son[v]) {
      Dfs(v);
    }

    if (rtype[ru] == 1) {
      if (--par_r1cnt[ridx[ru]] == 0) {
        assert(par_r1.back() == ru);
        par_r1.pop_back();
      }
    } else {
      r0_subtree_dfs_range[ridx[ru]].pb({dfs_l, dfsn});
    }
  };

  Dfs(0);
}

i64 Query(int rs, int rt) {
  if (rtype[rs] == 1) {
    if (rtype[rt] == 0) return ans10[ridx[rs]][ridx[rt]];
    return ans11[ridx[rs]][ridx[rt]];
  }

  i64 res = 0;
  REP(range, r0_subtree_dfs_range[ridx[rs]]) {
    const auto& pos = dfs_pos[rt];
    auto li = lower_bound(ALL(pos), range.first);
    auto ri = upper_bound(li, pos.end(), range.second);
    res += distance(li, ri);
  }
  return res;
}

void Solve() {
  int nq;
  scanf("%d%d%d",&n,&m,&nq);
  par.resize(n);
  home.resize(n);
  scanf("%d", &home[0]);
  --home[0];
  FOR(i, 1, n) {
    scanf("%d%d", &par[i], &home[i]);
    --par[i],--home[i];
  }

  big_cnt = round(sqrt(n));
  r_cnt.assign(n, 0);
  FOR(i, 0, n) ++r_cnt[home[i]];

  rtype.assign(m, 0);
  ridx.assign(m, -1);
  rtype_cnt.assign(2, 0);
  FOR(i, 0, m) {
    rtype[i] = r_cnt[i] > big_cnt;
    ridx[i] = rtype_cnt[rtype[i]]++;
  }

  Build();

  while (nq--) {
    int rs,rt;
    scanf("%d%d", &rs, &rt);
    --rs, --rt;
    printf("%lld\n", Query(rs, rt));
    fflush(stdout);
  }
}

int main() {
  int t = 1;
  // scanf("%d", &t);
  for (int i = 1; i <= t; ++i) {
    // printf("Case #%d: ", i);
    Solve();
  }

  return 0;
}

컴파일 시 표준 에러 (stderr) 메시지

regions.cpp: In function 'void Solve()':
regions.cpp:183:8: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  183 |   scanf("%d%d%d",&n,&m,&nq);
      |   ~~~~~^~~~~~~~~~~~~~~~~~~~
regions.cpp:186:8: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  186 |   scanf("%d", &home[0]);
      |   ~~~~~^~~~~~~~~~~~~~~~
regions.cpp:189:10: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  189 |     scanf("%d%d", &par[i], &home[i]);
      |     ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~
regions.cpp:209:10: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  209 |     scanf("%d%d", &rs, &rt);
      |     ~~~~~^~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...