Scan line segment tree +

Last wrote a O (N ^ {2})scanning line, in fact, can be re-optimization scan line, and today it said tree line optimization of scan lines.

Very simple idea of scanning lines, a plurality of rectangular, and the time required area, each rectangle can be represented by two four-tuple, (X, y_ {1}, {2} y_, mark)which xis one of the top right and bottom left rectangle of abscissa, y_ {1}, {2} y_is two top right and bottom left of the ordinate (Y_ {1} \ {2} y_ leq), markthere are two values, 1 and -1, meaning the right side and the left side of the scan time. When scanning the first encounter is the edge, the other is a side, because it is scanning from left to right, so the xcoordinates are the small side. Then we got 2Na quad, they will follow xin ascending order. Then all the Ycoordinates into an array, to re-sort, discretization. Before O (N ^ {2})practice with each value of an array to maintain an interval, so that every time when the need to update it again sweep array, they also solve the sweep again, in fact, you can use the tree line to maintain such a range.

Segment tree maintains two values, the number of times the current interval is covered, and covered over the inner side of the length and interval may be one more, it represents the length of the current interval, the convenience of calculation. If the current range is covered, apparently length and sum[k]=length[k], if that is not covered sum[k]=sum[k << 1] + sum[k<<1|1], update, due out side the edge there, so the front mark=1will be back mark=-1out offset, use less than marked down pass.

Note: It must be calculated first and then update.

#include <bits/stdc++.h>
using namespace std;
const int N = 310;
struct p{
	int x, y1, y2, mark;
} a[N];
int x[N], y[N];
int dy[N];
int len;
typedef struct SegementTree{
	int l[N * 4];
	int r[N * 4];
	int sum[N * 4];
	int cnt[N * 4];
	int length[N * 4];
	void build(int ll, int rr, int k){
		l[k] = ll;
		r[k] = rr;
		sum[k] = 0;
		cnt[k] = 0;
		if (ll == rr){
			length[k] = dy[ll + 1] - dy[ll];
			return;
		}
		int mid = (ll + rr) / 2;
		build(ll, mid, k << 1);
		build(mid + 1, rr, k << 1 | 1);
		length[k] = length[k << 1] + length[k << 1 | 1];
	}
	void update(int ll, int rr, int k, int mark){
		if (l[k] >= ll && r[k] <= rr){
			cnt[k] += mark;
			sum[k] = cnt[k] ? length[k] : sum[k << 1] + sum[k << 1 | 1];
			
			return ;
		}
		int mid = l[k] + r[k];
		mid /= 2;
		if (ll <= mid)update(ll, rr, k << 1, mark);
		if (rr > mid)update(ll, rr, k << 1 | 1, mark);
		sum[k] = cnt[k] ? length[k] : sum[k << 1] + sum[k << 1 | 1];
	}
} ST;
bool cmp(p& a, p& b){
	return a.x < b.x;
}
int get(int x){
	return lower_bound(dy + 1, dy + 1 + len, x) - dy;
}
ST st;
int main()
{
	freopen("./in.in", "r", stdin);
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++){
		scanf("%d %d", x + i, y + i);
		scanf("%d %d", x + i + n, y + i + n);
		a[i].x = x[i];
		a[i].y1 = y[i];
		a[i].y2 = y[i + n];
		a[i].mark = 1;
		a[i + n].x = x[i + n];
		a[i + n].y1 = y[i];
		a[i + n].y2 = y[i + n];
		a[i + n].mark = -1;
		dy[i] = y[i];
		dy[i + n] = y[i + n];
	}
	sort(a + 1, a + 1 + n, cmp);
	sort(dy + 1, dy + 1 + n + n);
	len = unique(dy + 1, dy + 1 + n + n) - dy - 1;
	st.build(1, len - 1, 1);
	int res = 0;
	for (int i = 1; i <= n + n; i++){
                //顺序不能错
		res += st.sum[1] * (a[i].x - a[i - 1].x);
		st.update(get(a[i].y1), get(a[i].y2) - 1, 1, a[i].mark);
	}
	printf("%d\n", res);
	return 0;
}

 

Published 204 original articles · won praise 13 · views 10000 +

Guess you like

Origin blog.csdn.net/weixin_43701790/article/details/104427140