QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#163389 | #7105. Pixel Art | ucup-team228 | WA | 767ms | 87964kb | C++20 | 8.0kb | 2023-09-04 02:49:22 | 2023-09-04 02:49:22 |
Judging History
answer
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct DSU {
static const int N = 1e6 + 10;
int Parent[N], Rank[N], Size[N], cnt;
void init(int n) {
for (int i = 1; i <= n; i++) {
Parent[i] = i, Rank[i] = 0, Size[i] = 1;
}
cnt = n;
}
int find(int v) {
if (Parent[v] == v) return v;
else return Parent[v] = find(Parent[v]);
}
void unite(int u, int v) {
u = find(u), v = find(v);
if (u == v) return;
if (Rank[u] < Rank[v]) swap(u, v);
if (Rank[v] == Rank[u]) Rank[u]++;
Parent[v] = u, cnt--;
Size[u] += Size[v];
}
};
DSU dsu;
#define close my_close
const int N = 5e5 + 10;
int r1[N], c1[N], r2[N], c2[N];
bool dead[N];
vector<pair<int, int>> row[N];
unordered_map<int, vector<pair<int, int>>> col;
unordered_map<int, set<pair<int, int>>> col_lef, col_rig;
vector<int> open[N], close[N];
ll cnt_black[N], cnt_comp[N];
void init(int n, int m, int k) {
for (int i = 0; i <= n + 1; i++) {
row[i].clear();
open[i].clear();
close[i].clear();
cnt_black[i] = 0;
}
col.clear();
col_lef.clear();
col_rig.clear();
for (int i = 1; i <= k; i++) {
dead[i] = false;
}
}
void merge(int n, int m, int k) {
for (int i = 1; i <= k; i++) {
if (dead[i]) {
continue;
} else if (r1[i] == r2[i]) {
row[r1[i]].emplace_back(c1[i], i);
} else {
col[c1[i]].emplace_back(r1[i], i);
}
}
for (int i = 1; i <= n; i++) {
sort(row[i].begin(), row[i].end());
for (int j = int(row[i].size()) - 1; j >= 1; j--) {
int x = row[i][j - 1].second;
int y = row[i][j].second;
if (c2[x] + 1 == c1[y]) {
dead[y] = true;
c2[x] = c2[y];
}
}
}
for (auto& [j, vec] : col) {
sort(vec.begin(), vec.end());
for (int i = int(vec.size()) - 1; i >= 1; i--) {
int x = vec[i - 1].second;
int y = vec[i].second;
if (r2[x] + 1 == r1[y]) {
dead[y] = true;
r2[x] = r2[y];
}
}
}
}
bool check(int i, int j) {
return max(c1[i], c1[j]) <= min(c2[i], c2[j]);
}
void solve(int n, int m, int k) {
for (int i = 1; i <= k; i++) {
if (r1[i] == r2[i]) {
col_lef[c1[i]].emplace(r1[i], i);
col_rig[c2[i]].emplace(r1[i], i);
}
}
const int init_k = k;
for (int i = 1; i <= k; i++) {
assert(i <= 2 * init_k);
if (r1[i] < r2[i]) {
auto lef = col_rig[c1[i] - 1].lower_bound({r1[i], 0});
auto rig = col_lef[c1[i] + 1].lower_bound({r1[i], 0});
bool ok_lef = lef != col_rig[c1[i] - 1].end() && lef->first <= r2[i];
bool ok_rig = rig != col_lef[c1[i] + 1].end() && rig->first <= r2[i];
if (ok_lef) {
if (ok_rig) {
if (lef->first <= rig->first) {
int j = lef->second;
col_rig[c2[j]].erase({r1[j], j});
c2[j] = c1[i];
col_rig[c2[j]].emplace(r1[j], j);
k++;
dead[k] = false;
r1[k] = r1[j] + 1;
r2[k] = r2[i];
c1[k] = c1[i];
c2[k] = c2[i];
r2[i] = r1[j] - 1;
} else {
int j = rig->second;
col_lef[c1[j]].erase({r1[j], j});
c1[j] = c1[i];
col_rig[c1[j]].emplace(r1[j], j);
k++;
dead[k] = false;
r1[k] = r1[j] + 1;
r2[k] = r2[i];
c1[k] = c1[i];
c2[k] = c1[i];
r2[i] = r1[j] - 1;
}
} else {
int j = lef->second;
col_rig[c2[j]].erase({r1[j], j});
c2[j] = c1[i];
col_rig[c2[j]].emplace(r1[j], j);
k++;
dead[k] = false;
r1[k] = r1[j] + 1;
r2[k] = r2[i];
c1[k] = c1[i];
c2[k] = c2[i];
r2[i] = r1[j] - 1;
}
} else if (ok_rig) {
int j = rig->second;
col_lef[c1[j]].erase({r1[j], j});
c1[j] = c1[i];
col_rig[c1[j]].emplace(r1[j], j);
k++;
dead[k] = false;
r1[k] = r1[j] + 1;
r2[k] = r2[i];
c1[k] = c1[i];
c2[k] = c1[i];
r2[i] = r1[j] - 1;
}
if (r2[i] < r1[i]) {
dead[i] = true;
}
}
}
merge(n, m, k);
/*
for (int i = 1; i <= k; i++) {
if (!dead[i]) {
cout << r1[i] << " " << c1[i] << " " << r2[i] << " " << c2[i] << "\n";
}
}
cout << "\n";
*/
for (int i = 1; i <= k; i++) {
if (!dead[i]) {
open[r1[i]].push_back(i);
close[r2[i] + 1].push_back(i);
cnt_black[r1[i]] += 1ll * (r2[i] - r1[i] + 1) * (c2[i] - c1[i] + 1);
}
}
for (int i = 1; i <= n; i++) {
cnt_black[i] += cnt_black[i - 1];
}
set<pair<int, int>> cur;
dsu.init(k);
int not_seen = k;
for (int r = 1; r <= n; r++) {
for (int i : open[r]) {
not_seen--;
vector<int> tmp;
while (true) {
auto it = cur.lower_bound({c1[i], 0});
if (it == cur.end() || !check(i, it->second)) {
break;
} else {
int j = it->second;
dsu.unite(i, j);
tmp.push_back(j);
cur.erase({c2[j], j});
}
}
for (int j : tmp) {
cur.insert({c2[j], j});
}
}
for (int i : close[r]) {
cur.erase({c2[i], i});
}
for (int i : open[r]) {
cur.insert({c2[i], i});
}
cnt_comp[r] = dsu.cnt - not_seen;
}
}
void stress() {
mt19937 rnd;
while (true) {
int n = rnd() % 100 + 1;
int m = rnd() % 100 + 1;
int k = rnd() % 100 + 1;
init(n, m, k);
vector<vector<bool>> tmp(n + 1, vector<bool>(m + 1, false));
for (int i = 1; i <= k; i++) {
while (true) {
r1[i] = rnd() % n + 1;
r2[i] = rnd() % n + 1;
c1[i] = rnd() % m + 1;
c2[i] = rnd() % m + 1;
if (r1[i] > r2[i]) swap(r1[i], r2[i]);
if (c1[i] > c2[i]) swap(c1[i], c2[i]);
if (rnd() % 2 == 0) {
r2[i] = r1[i];
} else {
c2[i] = c1[i];
}
}
}
solve(n, m, k);
cout << "OK" << endl;
}
exit(0);
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
#ifdef LOCAL
freopen("input.txt", "r", stdin);
#endif
// stress();
int t;
cin >> t;
while (t--) {
int n, m, k;
cin >> n >> m >> k;
init(n, m, k);
for (int i = 1; i <= k; i++) {
cin >> r1[i] >> c1[i] >> r2[i] >> c2[i];
}
solve(n, m, k);
for (int i = 1; i <= n; i++) {
cout << cnt_black[i] << " " << cnt_comp[i] << "\n";
}
}
#ifdef LOCAL
cout << "\nTime elapsed: " << double(clock()) / CLOCKS_PER_SEC << " s.\n";
#endif
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 4ms
memory: 54844kb
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: -100
Wrong Answer
time: 767ms
memory: 87964kb
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 100 50 100 50 200 1 100 50 200 100 200 100 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 ...
result:
wrong answer 8th lines differ - expected: '50 50', found: '100 50'