跳转至

扫描线

求矩阵面积并

例题

P5490 【模板】扫描线 - 洛谷

\(n\) 个矩阵的面积并

代码
C++
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
int __OneWan_2024 = [](){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    return 0;
}();
vector<int> idx(1, -1);
int sum[200010 << 3], cnt[200010 << 3];
void pushup(int p, int L, int R) {
    if (sum[p]) { // 有线段覆盖, 则为整个区间长度[L, R)
        cnt[p] = idx[R + 1] - idx[L];
    } else {
        cnt[p] = cnt[p << 1] + cnt[p << 1 | 1];
    }
}
void modify(int p, int L, int R, int QL, int QR, int k) {
    if (idx[R + 1] <= QL || idx[L] >= QR) return;
    if (QL <= idx[L] && idx[R + 1] <= QR) {
        sum[p] += k;
        pushup(p, L, R);
        return;
    }
    int mid = L + R >> 1;
    modify(p << 1, L, mid, QL, QR, k);
    modify(p << 1 | 1, mid + 1, R, QL, QR, k);
    pushup(p, L, R);
}
int main() {
    int n;
    cin >> n;
    vector<array<int, 4>> lines;
    for (int i = 0 ; i < n ; i++) {
        int x1, y1, x2, y2;
        cin >> x1 >> y1 >> x2 >> y2;
        idx.push_back(x1);
        idx.push_back(x2);
        lines.push_back({x1, x2, y1, 1});
        lines.push_back({x1, x2, y2, -1});
    }
    sort(begin(lines), end(lines), [&](const auto &x, const auto &y) {
        if (x[2] == y[2]) {
            return x[3] > y[3];
        }
        return x[2] < y[2];
    });
    idx.push_back(2e9);
    sort(begin(idx), end(idx));
    idx.resize(unique(begin(idx), end(idx)) - begin(idx));
    i64 ans = 0;
    int len = idx.size() - 2;
    for (int i = 0 ; i < (int) lines.size() - 1 ; i++) {
        auto [L, R, H, mark] = lines[i];
        modify(1, 1, len, L, R, mark);
        ans += 1LL * cnt[1] * (lines[i + 1][2] - H);
    }
    cout << ans << "\n";
    return 0;
}

P1856 [IOI1998] [USACO5.5] 矩形周长Picture

\(n\) 个矩阵的周长并

代码
C++
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
int __OneWan_2024 = [](){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    return 0;
}();
vector<int> idx(1, -200000);
int sum[200010 << 3], cnt[200010 << 3], mark[200010 << 3];
bool vis[200010 << 3][2];
void pushup(int p, int L, int R) {
    int x = p << 1, y = p << 1 | 1;
    if (sum[p]) { // 有线段覆盖, 则为整个区间长度[L, R)
        cnt[p] = idx[R + 1] - idx[L];
        vis[p][0] = vis[p][1] = true;
        mark[p] = 1;
    } else {
        cnt[p] = cnt[x] + cnt[y];
        vis[p][0] = vis[x][0];
        vis[p][1] = vis[y][1];
        mark[p] = mark[x] + mark[y];
        if (vis[x][1] && vis[y][0]) {
            mark[p]--;
        }
    }
}
void modify(int p, int L, int R, int QL, int QR, int k) {
    if (idx[R + 1] <= QL || idx[L] >= QR) return;
    if (QL <= idx[L] && idx[R + 1] <= QR) {
        sum[p] += k;
        pushup(p, L, R);
        return;
    }
    int mid = L + R >> 1;
    modify(p << 1, L, mid, QL, QR, k);
    modify(p << 1 | 1, mid + 1, R, QL, QR, k);
    pushup(p, L, R);
}
int main() {
    int n;
    cin >> n;
    vector<array<int, 4>> lines;
    for (int i = 0 ; i < n ; i++) {
        int x1, y1, x2, y2;
        cin >> x1 >> y1 >> x2 >> y2;
        idx.push_back(x1);
        idx.push_back(x2);
        lines.push_back({x1, x2, y1, 1});
        lines.push_back({x1, x2, y2, -1});
    }
    sort(begin(lines), end(lines), [&](const auto &x, const auto &y) {
        if (x[2] == y[2]) {
            return x[3] > y[3];
        }
        return x[2] < y[2];
    });
    idx.push_back(2e9);
    sort(begin(idx), end(idx));
    idx.resize(unique(begin(idx), end(idx)) - begin(idx));
    i64 ans = 0;
    int len = idx.size() - 2;
    int last = 0;
    for (int i = 0 ; i < (int) lines.size() - 1 ; i++) {
        auto [L, R, H, mrk] = lines[i];
        modify(1, 1, len, L, R, mrk);
        ans += llabs(last - cnt[1]);
        last = cnt[1];
        ans += 2LL * mark[1] * (lines[i + 1][2] - H);
    }
    ans += lines.back()[1] - lines.back()[0];
    cout << ans << "\n";
    return 0;
}