HDU 1255 覆盖的面积(线段树求矩形面积交)

题意:给出n个矩形,求出至少被两块矩形覆盖的面积。

思路:跟面积并类似的做法,不同的是每个节点要额外维护一个至少被覆盖两次的长度dcnt,此外还是要维护至少覆盖一次的长度cnt,然后每次由当前结点的cover标记和子节点的dcnt,cnt值来推出当前结点的dcnt,cnt值。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<map>
#include<set>
#include<ctime>
#define eps 1e-6
#define LL long long
#define pii pair<int, int>
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

const int MAXN = 2100;
//const int INF = 0x3f3f3f3f;
struct Node {
	int l, r, c;
	double lf, rf, cnt, dcnt;
} segTree[MAXN*4];
struct Line {
	int c;
	double x, y1, y2;
	bool operator < (const Line& E) const {
		return x < E.x;
	}
} line[MAXN];
double y[MAXN];
void build(int o, int L, int R) {
	Node& t = segTree[o];
	t.l = L;
	t.r = R;
	t.c = 0;
	t.lf = y[L];
	t.rf = y[R];
	t.cnt = 0;
	t.dcnt = 0;
	if(L+1 == R) return;
	int M =  (L+R) >> 1;
	build(o<<1, L, M);
	build((o<<1)|1, M, R);
}
void cal(int o) {
	Node& t = segTree[o];
	if(t.c > 1) {
		t.dcnt = t.cnt = t.rf - t.lf;
	}
	else if(t.c == 1) {
		t.cnt = t.rf - t.lf;
		if(t.l+1 == t.r) t.dcnt = 0;
		else t.dcnt = segTree[o<<1].cnt + segTree[(o<<1)|1].cnt;
	}
	else {
		if(t.l+1 == t.r) t.dcnt = t.cnt = 0;
		else t.dcnt = segTree[o<<1].dcnt + segTree[(o<<1)|1].dcnt, t.cnt = segTree[o<<1].cnt + segTree[(o<<1)|1].cnt;
	}
}
void update(int o, Line e) {
	Node& t = segTree[o];
	if(e.y1==t.lf && e.y2==t.rf) {
		t.c += e.c;
		cal(o);
		return;
	}
	if(e.y2 <= segTree[o<<1].rf) update(o<<1, e);
	else if(e.y1 >= segTree[(o<<1)|1].lf) update((o<<1)|1, e);
	else {
		Line tmp = e;
		tmp.y2 = segTree[o<<1].rf;
		update(o<<1, tmp);
		e.y1 = segTree[(o<<1)|1].lf;
		update((o<<1)|1, e);
	}
	cal(o);
}
int n, tot;
int main() {
    //freopen("input.txt", "r", stdin);
    int T;
    cin >> T;
	while(T--) {
		cin >> n;
		tot = 0;
		for(int i = 1; i <= n; i++) {
			double x1,x2,y1,y2;
			scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
			++tot;
			line[tot].y1 = y1;
			line[tot].y2 = y2;
			line[tot].x = x1;
			line[tot].c = 1;
			y[tot] = y1;
			++tot;
			line[tot].y1 = y1;
			line[tot].y2 = y2;
			line[tot].x = x2;
			line[tot].c = -1;
			y[tot] = y2;
		}
		sort(y+1, y+tot+1);
		sort(line+1, line+tot+1);
		build(1, 1, tot);
		double ans = 0;
		update(1, line[1]);
		for(int i = 2; i <= tot; i++) {
			ans += (line[i].x-line[i-1].x) * segTree[1].dcnt;
			update(1, line[i]);
		}
		printf("%.2f\n", ans);
	}
    return 0;
}


















  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值