제출 #614227

#제출 시각아이디문제언어결과실행 시간메모리
614227evenvalue늑대인간 (IOI18_werewolf)C++17
100 / 100
985 ms92144 KiB
#include "werewolf.h"
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;

template<typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
template<typename T>
using ordered_multiset = tree<T, null_type, less_equal<T>, rb_tree_tag, tree_order_statistics_node_update>;

template<typename T>
using min_heap = priority_queue<T, vector<T>, greater<T>>;
template<typename T>
using max_heap = priority_queue<T, vector<T>, less<T>>;

using int64 = long long;
using ld = long double;

constexpr int kInf = 1e9 + 10;
constexpr int64 kInf64 = 1e15 + 10;
constexpr int kMod = 1e9 + 7;

class MergeSortTree {
  const int n;
  vector<vector<int>> t;

  void build(const int x, const int l, const int r, const vector<int> &a) {
    if (l == r) {
      t[x] = {a[l]};
      return;
    }
    const int mid = (l + r) / 2;
    const int y = 2 * (mid - l + 1) + x;
    build(x + 1, l, mid, a);
    build(y, mid + 1, r, a);
    merge(t[x + 1].begin(), t[x + 1].end(),
          t[y].begin(), t[y].end(),
          back_inserter(t[x]));
  }

  int query(const int x, const int l, const int r, const int ql, const int qr, const int lo, const int hi) {
    if (ql <= l and r <= qr) {
      return (int) distance(lower_bound(t[x].begin(), t[x].end(), lo),
                            upper_bound(t[x].begin(), t[x].end(), hi));
    }
    const int mid = (l + r) / 2;
    const int y = 2 * (mid - l + 1) + x;
    if (qr <= mid) {
      return query(x + 1, l, mid, ql, qr, lo, hi);
    } else if (mid < ql) {
      return query(y, mid + 1, r, ql, qr, lo, hi);
    } else {
      return query(x + 1, l, mid, ql, qr, lo, hi) +
             query(y, mid + 1, r, ql, qr, lo, hi);
    }
  }

public:
  explicit MergeSortTree(const vector<int> &a) : n((int) a.size()), t(2 * n - 1) {
    build(0, 0, n - 1, a);
  }

  int query(const int l, const int r, const int lo, const int hi) {
    return query(0, 0, n - 1, l, r, lo, hi);
  }
};

class dsu {
  vector<int> e;
  vector<pair<int, int>> val;
  vector<pair<int, int>> range;

  int find(const int x) {
    return (e[x] < 0 ? x : e[x] = find(e[x]));
  }

public:
  explicit dsu(const int n) : e(n, -1), val(n, {0, 0}), range(n) {
    for (int i = 0; i < n; i++) {
      range[i] = {i, i};
    }
  }

  bool unite(int x, int y) {
    x = find(x), y = find(y);
    if (x > y) swap(x, y);
    if (x == y) return false;
    val[y] = {x, -e[x]};
    range[x] = {min(range[x].first, range[y].first),
                max(range[x].second, range[y].second)};
    e[x] += e[y];
    e[y] = x;
    return true;
  }

  vector<int> order() {
    vector<int> new_order(val.size());
    for (int i = 0; i < new_order.size(); i++) {
      new_order[i] = new_order[val[i].first] + val[i].second;
    }
    return new_order;
  }

  pair<int, int> get_range(const int x) {
    return range[find(x)];
  }
};

struct query {
  int s, e, l, r, i;
  int human_l, human_r;
  int werewolf_l, werewolf_r;
};

void humans(const vector<vector<int>> &g, vector<query> &queries, const vector<int> &order_human) {
  const int n = (int) g.size();
  sort(queries.begin(), queries.end(), [&](const query &q1, const query &q2) {
    return q1.l > q2.l;
  });
  dsu d(n);
  for (int l = n - 1, j = 0; l >= 0; l--) {
    for (const int y : g[l]) {
      if (y < l) continue;
      d.unite(order_human[l], order_human[y]);
    }
    while (j < queries.size() and queries[j].l == l) {
      const auto &[x, y] = d.get_range(order_human[queries[j].s]);
      queries[j].human_l = x;
      queries[j].human_r = y;
      j++;
    }
  }
}

void werewolfs(const vector<vector<int>> &g, vector<query> &queries, const vector<int> &order_werewolf) {
  const int n = (int) g.size();
  sort(queries.begin(), queries.end(), [&](const query &q1, const query &q2) {
    return q1.r < q2.r;
  });
  dsu d(n);
  for (int r = 0, j = 0; r < n; r++) {
    for (const int y : g[r]) {
      if (y > r) continue;
      d.unite(order_werewolf[r], order_werewolf[y]);
    }
    while (j < queries.size() and queries[j].r == r) {
      const auto &[x, y] = d.get_range(order_werewolf[queries[j].e]);
      queries[j].werewolf_l = x;
      queries[j].werewolf_r = y;
      j++;
    }
  }
}

void print_vec(const vector<int> &v, const string &name = "") {
  cerr << name << (name.empty() ? "" : ": ");
  for (const int x : v) {
    cerr << x << ' ';
  }
  cerr << '\n';
}

vector<int> check_validity(int n, vector<int> X, vector<int> Y, vector<int> S, vector<int> E, vector<int> L, vector<int> R) {
  const int m = (int) X.size();//number of edges
  const int q = (int) S.size();//number of queries
  vector<vector<int>> g(n);
  for (int i = 0; i < m; i++) {
    const int x = X[i], y = Y[i];
    g[x].push_back(y);
    g[y].push_back(x);
  }
  vector<query> queries(q);
  for (int i = 0; i < q; i++) {
    queries[i] = {S[i], E[i], L[i], R[i], i};
  }
  dsu human(n), werewolf(n);
  for (int l = n - 1; l >= 0; l--) {
    for (const int y : g[l]) {
      if (y < l) continue;
      human.unite(l, y);
    }
  }
  for (int r = 0; r < n; r++) {
    for (const int y : g[r]) {
      if (y > r) continue;
      werewolf.unite(r, y);
    }
  }
  vector<int> v(n);
  vector<int> order_human = human.order();
  vector<int> order_werewolf = werewolf.order();
  for (int i = 0; i < n; i++) {
    v[order_human[i]] = order_werewolf[i];
  }
  humans(g, queries, order_human);
  werewolfs(g, queries, order_werewolf);
  sort(queries.begin(), queries.end(), [&](const query &q1, const query &q2) {
    return q1.i < q2.i;
  });
  vector<int> ans(q);
  MergeSortTree mst(v);
  for (int i = 0; i < q; i++) {
    const auto &[s, e, l, r, idx,
                 hl, hr, wl, wr] = queries[i];
    ans[i] = (mst.query(hl, hr, wl, wr) > 0);
  }
  return ans;
}

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

werewolf.cpp: In member function 'std::vector<int> dsu::order()':
werewolf.cpp:100:23: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  100 |     for (int i = 0; i < new_order.size(); i++) {
      |                     ~~^~~~~~~~~~~~~~~~~~
werewolf.cpp: In function 'void humans(const std::vector<std::vector<int> >&, std::vector<query>&, const std::vector<int>&)':
werewolf.cpp:128:14: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<query>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  128 |     while (j < queries.size() and queries[j].l == l) {
      |            ~~^~~~~~~~~~~~~~~~
werewolf.cpp: In function 'void werewolfs(const std::vector<std::vector<int> >&, std::vector<query>&, const std::vector<int>&)':
werewolf.cpp:148:14: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<query>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  148 |     while (j < queries.size() and queries[j].r == r) {
      |            ~~^~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...