QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#162363 | #7105. Pixel Art | ucup-team133 | AC ✓ | 612ms | 28612kb | C++23 | 9.2kb | 2023-09-03 11:15:14 | 2023-09-04 04:31:20 |
Judging History
answer
#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
#ifdef LOCAL
#include <debug.hpp>
#else
#define debug(...) void(0)
#endif
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
using namespace std;
typedef long long ll;
#define all(x) begin(x), end(x)
constexpr int INF = (1 << 30) - 1;
constexpr long long IINF = (1LL << 60) - 1;
constexpr int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
template <class T> istream& operator>>(istream& is, vector<T>& v) {
for (auto& x : v) is >> x;
return is;
}
template <class T> ostream& operator<<(ostream& os, const vector<T>& v) {
auto sep = "";
for (const auto& x : v) os << exchange(sep, " ") << x;
return os;
}
template <class T, class U = T> bool chmin(T& x, U&& y) { return y < x and (x = forward<U>(y), true); }
template <class T, class U = T> bool chmax(T& x, U&& y) { return x < y and (x = forward<U>(y), true); }
template <class T> void mkuni(vector<T>& v) {
sort(begin(v), end(v));
v.erase(unique(begin(v), end(v)), end(v));
}
template <class T> int lwb(const vector<T>& v, const T& x) { return lower_bound(begin(v), end(v), x) - begin(v); }
void solve() {
int n, m, K;
cin >> n >> m >> K;
vector<int> lx(K), ly(K), rx(K), ry(K);
vector<vector<int>> row(n);
map<int, vector<int>> col;
for (int i = 0; i < K; i++) {
cin >> lx[i] >> ly[i] >> rx[i] >> ry[i];
lx[i]--, ly[i]--;
if (rx[i] - lx[i] == 1)
row[lx[i]].emplace_back(i);
else {
assert(ry[i] - ly[i] == 1);
col[ly[i]].emplace_back(i);
}
}
vector<vector<int>> revivers(n);
vector<vector<pair<int, int>>> es(n);
vector<int> rowsum(n, 0), colsum(n + 1, 0);
for (int i = 0; i < K; i++) {
revivers[lx[i]].emplace_back(i);
if (rx[i] - lx[i] == 1)
rowsum[lx[i]] += ry[i] - ly[i];
else {
colsum[lx[i]]++;
colsum[rx[i]]--;
}
}
for (int i = 0; i < n; i++) colsum[i + 1] += colsum[i];
{
// 横と横が横に隣接
for (int i = 0; i < n; i++) {
sort(begin(row[i]), end(row[i]), [&](int l, int r) { return ly[l] < ly[r]; });
for (int j = 0; j + 1 < int(row[i].size()); j++) {
int l = row[i][j], r = row[i][j + 1];
if (ry[l] == ly[r]) es[i].emplace_back(l, r);
}
}
}
{
// 横と横が縦に隣接
for (int i = 0; i + 1 < n; i++) {
vector<tuple<int, int, int>> events;
for (int& idx : row[i]) {
events.emplace_back(ly[idx], idx, 0);
events.emplace_back(ry[idx], -1, 0);
}
for (int& idx : row[i + 1]) {
events.emplace_back(ly[idx], idx, 1);
events.emplace_back(ry[idx], -1, 1);
}
sort(begin(events), end(events));
vector<int> cur(2, -1);
for (auto [tmp, idx, pos] : events) {
if (idx == -1)
cur[pos] = -1;
else {
cur[pos] = idx;
if (cur[0] >= 0 and cur[1] >= 0) es[i + 1].emplace_back(cur[0], cur[1]);
}
}
}
}
{
// 縦と縦が縦に隣接
for (auto& [y, v] : col) {
sort(begin(v), end(v), [&](int l, int r) { return lx[l] < lx[r]; });
for (int j = 0; j + 1 < int(v.size()); j++) {
int l = v[j], r = v[j + 1];
if (rx[l] == lx[r]) es[lx[r]].emplace_back(l, r);
}
}
}
{
// 縦と縦が横に隣接
for (auto& [y, v] : col) {
if (not col.count(y + 1)) continue;
auto& u = col[y + 1];
vector<tuple<int, int, int>> events;
for (int& idx : v) {
events.emplace_back(lx[idx], idx, 0);
events.emplace_back(rx[idx], -1, 0);
}
for (int& idx : u) {
events.emplace_back(lx[idx], idx, 1);
events.emplace_back(rx[idx], -1, 1);
}
sort(begin(events), end(events));
vector<int> cur(2, -1);
for (auto [tmp, idx, pos] : events) {
if (idx == -1)
cur[pos] = -1;
else {
cur[pos] = idx;
if (cur[0] >= 0 and cur[1] >= 0) es[tmp].emplace_back(cur[0], cur[1]);
}
}
}
}
{
// 横と縦が横に隣接
map<int, int> cur;
vector<vector<pair<int, int>>> events(n + 1);
for (auto& [y, v] : col) {
for (int& idx : v) {
events[lx[idx]].emplace_back(idx, y);
events[rx[idx]].emplace_back(-1, y);
}
}
for (int i = 0; i < n; i++) {
sort(begin(events[i]), end(events[i]));
for (auto [idx, pos] : events[i]) cur[pos] = idx;
for (int& idx : row[i]) {
{
int val = ly[idx] - 1;
if (val >= 0 and cur.count(val) and cur[val] >= 0) es[i].emplace_back(idx, cur[val]);
}
{
int val = ry[idx];
if (val < m and cur.count(val) and cur[val] >= 0) es[i].emplace_back(idx, cur[ry[idx]]);
}
}
}
}
{
// 横と縦が縦に隣接
vector<int> cur(n, -1);
map<int, vector<pair<int, int>>> events;
for (int i = 0; i < n; i++) {
for (int& idx : row[i]) {
events[ly[idx]].emplace_back(idx, i);
events[ry[idx]].emplace_back(-1, i);
}
}
for (auto& [y, v] : col) events[y].emplace_back(-2, -2);
for (auto& [i, v] : events) {
sort(begin(v), end(v));
for (auto [idx, pos] : v) {
if (pos == -2) continue;
cur[pos] = idx;
}
for (int& idx : col[i]) {
if (lx[idx] - 1 >= 0 and cur[lx[idx] - 1] >= 0) es[lx[idx]].emplace_back(idx, cur[lx[idx] - 1]);
if (rx[idx] < n and cur[rx[idx]] >= 0) es[rx[idx]].emplace_back(idx, cur[rx[idx]]);
}
}
}
atcoder::dsu dsu(K);
int ans = 0;
ll black = 0;
vector<int> cnt(K, 0);
auto REVIVE = [&](int v) {
v = dsu.leader(v);
ans -= (cnt[v] > 0);
cnt[v]++;
ans += (cnt[v] > 0);
};
auto MERGE = [&](int u, int v) {
u = dsu.leader(u), v = dsu.leader(v);
if (u == v) return;
ans -= (cnt[u] > 0);
ans -= (cnt[v] > 0);
int w = dsu.merge(u, v);
cnt[w] = cnt[u] + cnt[v];
ans += (cnt[w] > 0);
};
for (int i = 0; i < n; i++) {
black += rowsum[i];
black += colsum[i];
for (int& v : revivers[i]) REVIVE(v);
for (auto [u, v] : es[i]) MERGE(u, v);
cout << black << ' ' << ans << '\n';
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin >> T;
for (; T--;) solve();
return 0;
}
这程序好像有点Bug,我给组数据试试?
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 2ms
memory: 3608kb
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: 612ms
memory: 28612kb
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