Luogu P5490 [template] scan lines

Portal

As to dtx sister Topic exchange he told me

Sure enough, the most lovely tree line w


 

The scanning line can be used to find the area of ​​the rectangle and ...

There are some overlapping rectangles, and they find a set area of ​​the plane.

Placed directly online map of x

For each rectangle, the y coordinate is split into two modification operations (insertion and deletion), from bottom to top ordering;

The x coordinate of unique discrete, left to right ordering, maintenance each segment cut out of a tree line.

Suppose a from the x-axis, the line moves up - i.e. the scanning line!

Modifying encountered, the corresponding section on the line segment tree segment minus or plus, plus answer (sum of the current line segment length) * (the difference between this modification to the y coordinate of the next modification).

 

Segment tree in maintaining what information?

SUM [i] denotes the total length of the line section i. Obviously, sum [i] = sum [ls] + sum [rs].

However, the insertion and deletion, can not directly modify the value of the sum, as a segment may be covered by a plurality of rectangular ... it may also be deleted after another.

the lazy [i] representing the interval i is a rectangular cover a few. Thus, when the modification ++ directly on the lazy - just fine.

And must be further reduced before adding, so lazy mark will not be negative.

It can be found in each of the query are searching the entire range. Then only need to consider uploading, do not pass under.

If the lazy [i]> 0, i.e. overwritten, [i] = i, SUM length interval;

否则,sum[i] = sum[ls]+sum[rs]。

 

note:

In conventional - segment tree maintenance point, the (1,4) = (1,2) + (3,4);

But when the maintenance segment, the segment (2,3) are ignored.

Therefore, at the definition change: the interval [L, R] corresponding to the line segment (l, r + 1). This ensures that the length of the line segment is a line segment of the R-L + 1.

When modifying, because can not determine where the line, so the whole interval from the start, have two sons recursion.

When completely from (L> = r [now] +1 || R <= l [now]), can then be returned;

When completely covers (L <= l [now] && r [now] +1 <= R), the hit on the lazy.

After a node upload operation and determines the lazy, when the update value sum,

sum [now] = sum [ls] + sum [rs] cross-border situations that may arise, because the leaf node and no son!

So either special judge it, or to open 2 times the space ...

(Hey ... remember the first time to write segment tree when 1 thing ...)

 .

code show as below

 

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#define MogeKo qwq
using namespace std;
#define ls (now<<1)
#define rs (now<<1|1)

const int maxn = 2e5+10;
int n,x_1,y_1,x_2,y_2,tot;
long long ans;
int X[maxn<<1];
int l[maxn<<2],r[maxn<<2],sum[maxn<<2],lazy[maxn<<2];

struct ScanLine {
    int l,r,h,val;
    bool operator < (const ScanLine & N) const {
        if(h == N.h) return val > N.val;
        return h < N.h;
    }
} line[maxn<<1];

void build(int L,int R,int now) {
    l[now] = L;
    r[now] = R;
    sum[now] = lazy[now] = 0;
    if(L == R) return;
    int mid = (l[now]+r[now]) >> 1;
    build(L,mid,ls);
    build(mid+1,R,rs);
}

void pushup(int now) {
    if(lazy[now])
        sum[now] = X[r[now]+1] - X[l[now]];
    else if(l[now] == r[now])
        sum[now] = 0;
    else
        sum[now] = sum[ls] + sum[rs];
}

void modify(int L,int R,int c,int now) {
    if(L >= X[r[now]+1] || R <= X[l[now]])
        return;
    if(L <= X[l[now]] && X[r[now]+1] <= R) {
        lazy[now] += c;
        pushup(now);
        return;
    }
    modify(L,R,c,ls);
    modify(L,R,c,rs);
    pushup(now);
}

int main() {
    scanf("%d",&n);
    for(int i = 1; i <= n; i++) {
        scanf("%d%d%d%d",&x_1,&y_1,&x_2,&y_2);
        line[2*i-1] = (ScanLine) {x_1,x_2,y_1,1};
        line[2*i] = (ScanLine) {x_1,x_2,y_2,-1};
        X[2*i-1] = x_1;
        X[2*i] = x_2;
    }
    n <<= 1;
    sort(line+1,line+n+1);
    sort(X+1,X+n+1);
    tot = unique(X+1,X+n+1)-X-1;
    build(1,tot-1,1);
    for(int i = 1; i < n; i++) {
        modify(line[i].l,line[i].r,line[i].val,1);
        ans += (long long)sum[1] * (line[i+1].h - line[i].h);
    }
    printf("%lld",ans);
    return 0;
}

 

 

 

Guess you like

Origin www.cnblogs.com/mogeko/p/11801282.html