Codeforces 1041E. Divide Square 【扫描线】

题目链接
题目描述
在一个\(10^6\)x\(10^6\)的正方形中,给你n条垂直于y中的线和m条垂直于x轴的线,每一条线至少有一个端点和正方形相连。问最后这些组成的线构成了多少个新的小矩阵。
思路
考虑扫描线的思想,从左到右对平行于y轴的线的每个x进行扫描。
每个交点,必定形成一个新的矩形,对于范围为0~1000000的线来说,会额外增加一个区域,那么可以看成在矩形的初始状态就进行了额外的划分。答案就变成了初始所划分好的区域+所有交点数量。
先将所有水平的线段读入,根据扫描线的思想差分处理l和r+1,然后读入每条垂直的线。排序以后枚举每个x点,就相当于对于x点,求其上下界中点的数量,相当于一个差分以后的前缀和处理,同时每次更新一下整个上下区间的值即可。
代码

#include<bits/stdc++.h>
using namespace std;

typedef long long LL;
const int N = 1e6 + 10;
struct edge1 {
	int x, y, d;
	friend bool operator < (const edge1 a, const edge1 b) {
		return a.x < b.x;
	}
}a[N << 1];
struct edge2 {
	int x, l, r;
	friend bool operator < (const edge2 a, const edge2 b) {
		return a.x < b.x;
	}
}b[N << 1];
LL tr[N << 1];

int lowbit(int x) {
	return x & -x;
}

void update(int x, int num) {
	for(int i = x; i <= 1e6 + 2; i += lowbit(i)) tr[i] += num;
}

LL sum(int x) {
	LL sum = 0;
	for(int i = x; i > 0; i -= lowbit(i)) sum += tr[i];
	return sum;
}

void solve() {
	LL res = 1, idx = 0;
	int n, m; cin >> n >> m;
	for(int i = 1; i <= n; i++) {
		int y, l, r; scanf("%d%d%d", &y, &l, &r);
		if(l == 0 && r == 1e6) res++;
		a[++idx] = {l, y, 1};
		a[++idx] = {r + 1, y, -1};
	}
	for(int i = 1; i <= m; i++) {
		int x, l, r; scanf("%d%d%d", &x, &l, &r);
		if(l == 0 && r == 1e6) res++;
		b[i] = {x, l, r};
	}
	sort(a + 1, a + 1 + idx);
	sort(b + 1, b + 1 + m);
	int pt1 = 1, pt2 = 1;
	for(; pt1 <= idx && a[pt1].x == 0; pt1++) update(a[pt1].y, a[pt1].d);

	for(int i = 1; i <= 1e6 + 10; i++) {
            for(; pt1 <= idx && a[pt1].x == i; pt1++) {
			update(a[pt1].y, a[pt1].d);
		}
	    for(; pt2 <= m && b[pt2].x == i; pt2++)  {
			res += sum(b[pt2].r) - sum(b[pt2].l - 1);
		}
	}
	printf("%lld\n", res);
}

int main() {
//	freopen("in.txt", "r", stdin);
	solve();
	return 0;
}

posted @ 2020-08-25 00:21  这知识他不进我的脑子  阅读(151)  评论(0编辑  收藏  举报