Solution
扫描线
读题的时候发现重点是,这就大大简化了这道题。
首先我们先考虑如何计算某一行的贡献,我们发现如果我们知道连续的白色块的,那么他的贡献就是
,那么我们创建一个set<pair<int, int>>去维护当前行的连续白色格子的断点
即可,我们对每一列的计算可以将列旋转90度看作行来处理,将
改为
互换即可。需要注意的是当
的时候,两次扫描的结果都是
的格子,是一样的,所以只需要横竖里任选一遍扫描即可。
扫描线同理,标记入边操作和出边操作,进行排序之后维护。
del:入边的时候插入黑色格子,即删去set中的(若存在),这点和珂朵莉树很相像。
add:出边的时候我们插入之前被删去的,合并格子,这里需要注意,排序的时候是先根据h从低到高,同时del操作排在后面,这样就比会避免先删后加,删的时候还没有加进去的问题。合并操作即先看下左边是否能合并,是否存在
,再看下右边是否存在
然后将其都删去,更新
并插入
即可。
Code
#include <bits/stdc++.h>
#define l first
#define r second
#define mp make_pair
#define lowbit(x) ((x) & -(x))
using namespace std;
using ll = long long;
using ull = unsigned long long;
using pii = pair<int, int>;
constexpr double eps = 1e-8;
constexpr int NINF = 0xc0c0c0c0;
constexpr int INF = 0x3f3f3f3f;
constexpr ll LNINF = 0xc0c0c0c0c0c0c0c0;
constexpr ll LINF = 0x3f3f3f3f3f3f3f3f;
constexpr ll mod = 1e9 + 7;
constexpr ll N = 1e6 + 5;
int n, w, h, c, m, cnt1, cnt2;
ll ans, res;
struct node {
int l, r, h, op;
inline bool operator <(const node & T) const {
return h == T.h ? op < T.op : h < T.h;
}
} a[N], b[N];
set<pair<int, int>> s;
void dw(int l, int r) {
res -= max(r - l + 2 - m, 0);
}
void update(int l, int r) {
s.insert({l, r});
res += max(r - l + 2 - m, 0);
}
void del(int l, int r) {
auto k = s.lower_bound({l, r});
if (k == s.end() || k->l > r) k--;
auto [L, R] = *k;
s.erase(k);
dw(L, R);
if (L < l) update(L, l - 1);
if (R > r) update(r + 1, R);
}
void add(int l, int r) {
auto k = s.lower_bound({l, r});
if ((!s.empty() && k != s.begin())) {
k--;
if (k->r == l - 1) {
l = k->l;
dw(k->l, k->r);
s.erase(k);
}
}
k = s.lower_bound({l, r});
if (k != s.end()) {
if (k->l == r + 1) {
r = k->r;
dw(k->l, k->r);
s.erase(k);
}
}
update(l, r);
}
void solve(int n, int x, node *a, int cnt) {
s.clear();
sort(a + 1, a + 1 + cnt);
res = 0;
a[0] = {1, n, 1, 0};
a[cnt + 1].h = x + 1;
for (int i = 0; i <= cnt; ) {
int h = a[i].h;
while (i <= cnt && h == a[i].h) {
if (a[i].op == 1) del(a[i].l, a[i].r);
else add(a[i].l, a[i].r);
i++;
}
ans += res * (a[i].h - h);
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> w >> h >> n >> c >> m;
for (int i = 0; i < n; i++) {
int x1, y1, x2, y2;
cin >> x1 >> y1 >> x2 >> y2;
a[++cnt1] = {x1, x2, y1, 1};
a[++cnt1] = {x1, x2, y2 + 1, 0};
b[++cnt2] = {y1, y2, x1, 1};
b[++cnt2] = {y1, y2, x2 + 1, 0};
}
solve(w, h, a, cnt1);
if (m != 1) solve(h, w, b, cnt2);
cout << ans << '\n';
return 0;
}
京公网安备 11010502036488号