QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#161919#7105. Pixel Artucup-team987#AC ✓898ms68792kbC++239.4kb2023-09-03 02:45:222023-09-04 04:31:11

Judging History

你现在查看的是最新测评结果

  • [2023-09-04 04:31:11]
  • 自动重测本题所有获得100分的提交记录
  • 测评结果:AC
  • 用时:898ms
  • 内存:68792kb
  • [2023-09-03 02:45:22]
  • 评测
  • 测评结果:100
  • 用时:882ms
  • 内存:68996kb
  • [2023-09-03 02:45:22]
  • 提交

answer

#if __INCLUDE_LEVEL__ == 0

#include <bits/stdc++.h>

using namespace std;

#include __BASE_FILE__

namespace {

void solve() {
  int h, w, k;
  cin >> tie(h, w, k);
  vector<vector<int>> lj(h);
  vector<vector<int>> rj(h);
  static vector<vector<int>> li(1e5);
  static vector<vector<int>> ri(1e5);
  vector<int> rep_w;
  while (k--) {
    int i1, j1, i2, j2;
    cin >> tie(i1, j1, i2, j2);
    --i1, --j1, --i2, --j2;
    if (i1 == i2) {
      lj[i1].push_back(j1);
      rj[i1].push_back(j2 + 1);
    } else if (j1 == j2) {
      li[j1].push_back(i1);
      ri[j1].push_back(i2 + 1);
      rep_w.push_back(j1);
    } else {
      assert(false);
    }
  }
  ranges::sort(rep_w);
  ALL(rep_w.erase, ranges::unique(rep_w));
  for (int i : rep(h)) {
    ranges::sort(lj[i]);
    ranges::sort(rj[i]);
  }
  for (int j : rep_w) {
    ranges::sort(li[j]);
    ranges::sort(ri[j]);
  }
  auto is_black = [&](int i, int j) -> bool {
    if (i < 0 || h <= i || j < 0 || w <= j) {
      return false;
    }
    if (auto it = ranges::upper_bound(rj[i], j);
        it != rj[i].end() && lj[i][it - rj[i].begin()] <= j) {
      return true;
    }
    if (auto it = ranges::upper_bound(ri[j], i);
        it != ri[j].end() && li[j][it - ri[j].begin()] <= i) {
      return true;
    }
    return false;
  };
  vector<pair<int, int>> cells;
  auto add = [&](int i, int j) {
    if (is_black(i, j)) {
      cells.emplace_back(i, j);
    }
  };
  for (int i : rep(h)) {
    for (int t : rep(lj[i].size())) {
      add(i, lj[i][t]);
      add(i, rj[i][t] - 1);
      add(i - 1, lj[i][t]);
      add(i - 1, rj[i][t] - 1);
      add(i + 1, lj[i][t]);
      add(i + 1, rj[i][t] - 1);
      add(i, lj[i][t] - 1);
      add(i, rj[i][t]);
    }
  }
  for (int j : rep_w) {
    for (int t : rep(li[j].size())) {
      add(li[j][t], j);
      add(ri[j][t] - 1, j);
      add(li[j][t], j - 1);
      add(ri[j][t] - 1, j - 1);
      add(li[j][t], j + 1);
      add(ri[j][t] - 1, j + 1);
      add(li[j][t] - 1, j);
      add(ri[j][t], j);
    }
  }
  ranges::sort(cells);
  ALL(cells.erase, ranges::unique(cells));
  int n = cells.size();
  vector<HashMap<int, int>> hm(h);
  for (int v : rep(n)) {
    auto [i, j] = cells[v];
    hm[i][j] = v;
  }
  vector<vector<int>> g(n);
  for (int v : rep(n)) {
    auto [i, j] = cells[v];
    for (auto [ni, nj] : {pair{1, 0}, {0, 1}, {-1, 0}, {0, -1}}) {
      ni += i;
      nj += j;
      if (ni < 0 || h <= ni || nj < 0 || w <= nj) {
        continue;
      }
      if (hm[ni].find(nj) != hm[ni].end()) {
        int u = hm[ni][nj];
        if (u < v) {
          g[v].push_back(u);
        } else {
          g[u].push_back(v);
        }
      }
    }
  }
  vector<vector<int>> js(h);
  static vector<vector<int>> is(1e5);
  for (int v : rep(n)) {
    auto [i, j] = cells[v];
    js[i].push_back(j);
    is[j].push_back(i);
  }
  for (int i : rep(h)) {
    for (int t : rep(lj[i].size())) {
      int u = -1;
      for (int j : ranges::subrange(ranges::lower_bound(js[i], lj[i][t]),
                                    ranges::lower_bound(js[i], rj[i][t]))) {
        int v = hm[i][j];
        if (~u) {
          if (u < v) {
            g[v].push_back(u);
          } else {
            g[u].push_back(v);
          }
        }
        u = v;
      }
    }
  }
  for (int j : rep_w) {
    for (int t : rep(li[j].size())) {
      int u = -1;
      for (int i : ranges::subrange(ranges::lower_bound(is[j], li[j][t]),
                                    ranges::lower_bound(is[j], ri[j][t]))) {
        int v = hm[i][j];
        if (~u) {
          if (u < v) {
            g[v].push_back(u);
          } else {
            g[u].push_back(v);
          }
        }
        u = v;
      }
    }
  }
  vector<int> ans(h, -1);
  atcoder::dsu d(n);
  int cur = 0;
  for (int v : rep(n)) {
    ++cur;
    for (int u : g[v]) {
      if (u < v) {
        if (!d.same(u, v)) {
          d.merge(u, v);
          --cur;
        }
      }
    }
    ans[cells[v].first] = cur;
  }
  {
    int prv = 0;
    for (int i : rep(h)) {
      if (ans[i] == -1) {
        ans[i] = prv;
      }
      prv = ans[i];
    }
  }
  vector<int64_t> c(h + 1);
  for (int j : rep_w) {
    for (int t : rep(li[j].size())) {
      ++c[li[j][t]];
      --c[ri[j][t]];
    }
  }
  for (int i : rep(h)) {
    c[i + 1] += c[i];
  }
  for (int i : rep(h)) {
    for (int t : rep(lj[i].size())) {
      c[i] += rj[i][t] - lj[i][t];
    }
  }
  for (int i : rep(h)) {
    c[i + 1] += c[i];
  }
  for (int i : rep(h)) {
    print(c[i], ans[i]);
  }
  for (int j : rep_w) {
    li[j].clear();
    ri[j].clear();
  }
  for (auto [_, j] : cells) {
    is[j].clear();
  }
}

}  // namespace

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);

  int t;
  cin >> t;
  while (t--) {
    solve();
  }
}

#else  // __INCLUDE_LEVEL__

#undef assert
#define assert(expr) (expr) || (__builtin_unreachable(), 0)

#define ALL(f, r, ...) \
  [&](auto&& _) { return f(begin(_), end(_), ##__VA_ARGS__); }(r)

#include <ext/pb_ds/assoc_container.hpp>

namespace atcoder {

// Implement (union by size) + (path compression)
// Reference:
// Zvi Galil and Giuseppe F. Italiano,
// Data structures and algorithms for disjoint set union problems
struct dsu {
 public:
  dsu() : _n(0) {}
  explicit dsu(int n) : _n(n), parent_or_size(n, -1) {}

  int merge(int a, int b) {
    assert(0 <= a && a < _n);
    assert(0 <= b && b < _n);
    int x = leader(a), y = leader(b);
    if (x == y) return x;
    if (-parent_or_size[x] < -parent_or_size[y]) std::swap(x, y);
    parent_or_size[x] += parent_or_size[y];
    parent_or_size[y] = x;
    return x;
  }

  bool same(int a, int b) {
    assert(0 <= a && a < _n);
    assert(0 <= b && b < _n);
    return leader(a) == leader(b);
  }

  int leader(int a) {
    assert(0 <= a && a < _n);
    if (parent_or_size[a] < 0) return a;
    return parent_or_size[a] = leader(parent_or_size[a]);
  }

  int size(int a) {
    assert(0 <= a && a < _n);
    return -parent_or_size[leader(a)];
  }

  std::vector<std::vector<int>> groups() {
    std::vector<int> leader_buf(_n), group_size(_n);
    for (int i = 0; i < _n; i++) {
      leader_buf[i] = leader(i);
      group_size[leader_buf[i]]++;
    }
    std::vector<std::vector<int>> result(_n);
    for (int i = 0; i < _n; i++) {
      result[i].reserve(group_size[i]);
    }
    for (int i = 0; i < _n; i++) {
      result[leader_buf[i]].push_back(i);
    }
    result.erase(
        std::remove_if(result.begin(), result.end(),
                       [&](const std::vector<int>& v) { return v.empty(); }),
        result.end());
    return result;
  }

 private:
  int _n;
  // root node: -1 * component size
  // otherwise: parent
  std::vector<int> parent_or_size;
};

}  // namespace atcoder

template <class T, class U = T>
bool chmin(T& x, U&& y) {
  return y < x && (x = forward<U>(y), true);
}

template <class T, class U = T>
bool chmax(T& x, U&& y) {
  return x < y && (x = forward<U>(y), true);
}

namespace std {

template <class T1, class T2>
istream& operator>>(istream& is, pair<T1, T2>& p) {
  return is >> p.first >> p.second;
}

template <class... Ts>
istream& operator>>(istream& is, tuple<Ts...>& t) {
  return apply([&is](auto&... xs) -> istream& { return (is >> ... >> xs); }, t);
}

template <class... Ts>
istream& operator>>(istream& is, tuple<Ts&...>&& t) {
  return is >> t;
}

template <class R, enable_if_t<!is_convertible_v<R, string>>* = nullptr>
auto operator>>(istream& is, R&& r) -> decltype(is >> *begin(r)) {
  for (auto&& e : r) {
    is >> e;
  }
  return is;
}

template <class T1, class T2>
ostream& operator<<(ostream& os, const pair<T1, T2>& p) {
  return os << p.first << ' ' << p.second;
}

template <class... Ts>
ostream& operator<<(ostream& os, const tuple<Ts...>& t) {
  auto f = [&os](const auto&... xs) -> ostream& {
    [[maybe_unused]] auto sep = "";
    ((os << exchange(sep, " ") << xs), ...);
    return os;
  };
  return apply(f, t);
}

template <class R, enable_if_t<!is_convertible_v<R, string_view>>* = nullptr>
auto operator<<(ostream& os, R&& r) -> decltype(os << *begin(r)) {
  auto sep = "";
  for (auto&& e : r) {
    os << exchange(sep, " ") << e;
  }
  return os;
}

}  // namespace std

template <class... Ts>
void print(Ts&&... xs) {
  cout << tie(xs...) << '\n';
}

inline auto rep(int l, int r) { return views::iota(min(l, r), r); }
inline auto rep(int n) { return rep(0, n); }
inline auto rep1(int l, int r) { return rep(l, r + 1); }
inline auto rep1(int n) { return rep(1, n + 1); }
inline auto per(int l, int r) { return rep(l, r) | views::reverse; }
inline auto per(int n) { return per(0, n); }
inline auto per1(int l, int r) { return per(l, r + 1); }
inline auto per1(int n) { return per(1, n + 1); }

struct Splitmix64Hash {
  static uint64_t splitmix64(uint64_t x) {
    x += 0x9e3779b97f4a7c15;
    x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
    x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
    return x ^ (x >> 31);
  }
  size_t operator()(uint64_t x) const {
    static const uint64_t r =
        std::chrono::steady_clock::now().time_since_epoch().count();
    return splitmix64(x + r);
  }
};

template <class Key, class T>
using HashMap = __gnu_pbds::gp_hash_table<Key, T, Splitmix64Hash>;

#endif  // __INCLUDE_LEVEL__

这程序好像有点Bug,我给组数据试试?

詳細信息

Test #1:

score: 100
Accepted
time: 4ms
memory: 10356kb

input:

3
2 5 2
1 1 1 2
2 3 2 5
2 5 2
1 1 1 3
2 3 2 5
3 3 3
1 1 1 2
3 1 3 2
1 3 2 3

output:

2 1
5 2
3 1
6 1
3 1
4 1
6 2

result:

ok 7 lines

Test #2:

score: 0
Accepted
time: 898ms
memory: 68792kb

input:

2130
2 5 2
1 1 1 2
2 3 2 5
2 5 2
1 1 1 3
2 3 2 5
3 3 3
1 1 1 2
3 1 3 2
1 3 2 3
3 100 51
1 2 2 2
1 4 2 4
1 6 2 6
1 8 2 8
1 10 2 10
1 12 2 12
1 14 2 14
1 16 2 16
1 18 2 18
1 20 2 20
1 22 2 22
1 24 2 24
1 26 2 26
1 28 2 28
1 30 2 30
1 32 2 32
1 34 2 34
1 36 2 36
1 38 2 38
1 40 2 40
1 42 2 42
1 44 2 44
...

output:

2 1
5 2
3 1
6 1
3 1
4 1
6 2
50 50
100 50
200 1
50 50
150 1
200 1
2 1
4 1
6 1
8 1
10 1
12 1
14 1
16 1
18 1
20 1
22 1
24 1
26 1
28 1
30 1
32 1
34 1
36 1
38 1
40 1
42 1
44 1
46 1
48 1
50 1
52 1
54 1
56 1
58 1
60 1
62 1
64 1
66 1
68 1
70 1
72 1
74 1
76 1
78 1
80 1
82 1
84 1
86 1
88 1
90 1
92 1
94 1
96 1...

result:

ok 355756 lines

Extra Test:

score: 0
Extra Test Passed