[Luogu] 被污染的河流

https://www.luogu.org/problemnew/show/P3875

线段树扫描线求矩形面积并

扫描线的线段树有点奇怪,修改的标记不会下传,标记的意义是当前区间被完整地覆盖了多少次,我们可以根据这个标记来求这个区间覆盖了至少一次的长度和至少两次的长度

:数组大小

#include <iostream>
#include <cstdio>
#include <algorithm>

#define gc getchar()

using std:: sort;
using std:: cout;
using std:: min;
using std:: max;
const int N = 10100;

int n, js;
int X[N << 2], W[N << 4], F[N << 4];
struct Node {int x_1, x_2, h, how;} lp[N << 1];

inline int read() {
    int x = 0; char c = gc;
    while(c < '0' || c > '9') c = gc;
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc;
    return x;
}

inline void Add(int _x_1, int _y_1, int _x_2, int _y_2) {
    if(_y_1 == _y_2) {
        int _1 = _x_1, _2 = _x_2;
        _x_1 = min(_1, _2); _x_2 = max(_1, _2);
        lp[++ js].x_1 = _x_1; lp[js].x_2 = _x_2; lp[js].h = _y_1 - 1; lp[js].how = 1; X[js] = _x_1;
        lp[++ js].x_1 = _x_1; lp[js].x_2 = _x_2; lp[js].h = _y_1 + 1; lp[js].how = -1; X[js] = _x_2;
    } else {
        int _1 = _y_1, _2 = _y_2;
        _y_1 = min(_1, _2); _y_2 = max(_1, _2);
        lp[++ js].x_1 = _x_1 - 1; lp[js].x_2 = _x_1 + 1; lp[js].h = _y_1; lp[js].how = 1; X[js] = _x_1 - 1;
        lp[++ js].x_1 = _x_1 - 1; lp[js].x_2 = _x_1 + 1; lp[js].h = _y_2; lp[js].how = -1; X[js] = _x_1 + 1;
    }
}

inline bool cmp(Node a, Node b) {return a.h < b.h;}

int Find(int num, int r_) {
    int L = 1, R = r_, ret;
    while(L <= R) {
        int Mid = (L + R) >> 1;
        if(X[Mid] <= num) L = Mid + 1, ret = Mid;
        else R = Mid - 1;
    }
    return ret;
}

#define lson jd << 1
#define rson jd << 1 | 1

void Pushup(int jd, int l, int r) {
    if(F[jd]) W[jd] = X[r + 1] - X[l];
    else if(l == r) W[jd] = 0;
    else W[jd] = W[lson] + W[rson];
}

void Sec_G(int l, int r, int jd, int x, int y, int how) {
    if(x <= l && r <= y) {F[jd] += how; Pushup(jd, l, r); return ;}
    int mid = (l + r) >> 1;
    if(x <= mid) Sec_G(l, mid, lson, x, y, how);
    if(y > mid)  Sec_G(mid + 1, r, rson, x, y, how);
    Pushup(jd, l, r);
}

int main() {
    n = read();
    for(int i = 1; i <= n; i ++) {
        int x_1 = read(), y_1 = read(), x_2 = read(), y_2 = read();
        Add(x_1, y_1, x_2, y_2);
    }
    sort(X + 1, X + js + 1);
    sort(lp + 1, lp + js + 1, cmp);
    int k = 1;
    for(int i = 2; i <= js; i ++) if(X[i] != X[i + 1]) X[++ k] = X[i];
    long long Answer = 0;
    for(int i = 1; i < js; i ++) {
        int l = Find(lp[i].x_1, k), r = Find(lp[i].x_2, k) - 1;
        Sec_G(1, k - 1, 1, l, r, lp[i].how);
        Answer += W[1] * (lp[i + 1].h - lp[i].h);
    }
    cout << Answer;
    return 0;
}
原文地址:https://www.cnblogs.com/shandongs1/p/8543201.html