污染面积
问题描述
小明的家旁边有条河流,但最近,周围的三个工厂开始向这条河排放污水,这条河的一部分被污染了,被一个工厂污染的部分可以看做一个矩形,现在小明想知道这条河被污染的面积是多少。
输入
第一行一个整数t,表示有多少组数据,之后每一组数据包括三行,每一行有lx, ly, rx, ry四个整数,表示被一个工厂污染的矩形的左下角与右上角,保证每个数都在[-100000,100000]之间,lx<rx,ly<ry。
输出
对于每组数据输出一行,每行一个整数表示被污染的面积。
样例输入
1
1 1 4 4
3 2 6 3
5 1 8 4
样例输出
19
思路。这题很简单,就是简单的容斥原理即可
#include <iostream>
#include <algorithm>
#include <cassert>
using namespace std;
#include <stdio.h>
struct point {
int x, y;
point(int x,int y) :x(x),y(y) {}
point(){}
};
typedef long long ll;
struct rect {
point l, r;
rect() {}
rect(point a, point b) : l(a), r(b) {}
ll area() { return (r.x - l.x) * 1LL * (r.y - l.y); }
rect getit(rect s) {
int left, right, up, down;
if (l.x >= s.r.x||l.y >= s.r.y||r.x <= s.l.x||r.y <= s.l.y)
return rect(point(0,0),point(0,0));
left = max(l.x, s.l.x);
right = min(r.x, s.r.x);
down = max(l.y, s.l.y);
up = min(r.y, s.r.y);
return rect(point(left,down),point(right,up));
}
};
int main(void)
{
int t;
scanf("%d", &t);
while (t--) {
rect s1, s2, s3;
int a, b, c, d;
scanf("%d%d%d%d", &a, &b, &c, &d);
assert(a < c&&b < d);
s1 = rect(point(a,b), point(c,d));
scanf("%d%d%d%d", &a, &b, &c, &d);
assert(a < c&&b < d);
s2 = rect(point(a,b),point(c,d));
scanf("%d%d%d%d", &a, &b, &c, &d);
assert(a < c&&b < d);
s3 = rect(point(a,b),point(c,d));
ll res = s1.area() + s2.area() + s3.area() -
s1.getit(s2).area() - s1.getit(s3).area()
- s2.getit(s3).area() + s1.getit(s2).getit(s3).area();
printf("%lld\n", res);
}
return 0;
同时,这题还可以用扫描线的方法来做:
讲的通俗易懂
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int MAXN = 10000;
struct line{
int ll,rr,h;
int c;
line(){};
line(int ll,int rr,int h,int c):ll(ll),rr(rr),h(h),c(c){};
bool operator<(const line &b){
return this->h<b.h;
}
};
struct node{
int ll,rr;
int cover;
int sum;
};
int x_ind[MAXN];
node tree[MAXN*4];
line lines[MAXN];
int N;
void create(int root,int ll,int rr){
tree[root].ll = x_ind[ll];
tree[root].rr = x_ind[rr];
tree[root].cover = 0;
tree[root].sum = 0;
if(rr - ll == 1) return;
int mid = (ll+rr)/2;
create(root*2,ll, mid);
create(root*2+1,mid,rr);
}
void update(int root , int ll, int rr,int cover){
if(tree[root].rr<=ll || tree[root].ll>= rr) return;
if(tree[root].ll>=ll && tree[root].rr <= rr){
tree[root].cover += cover;
// return;
}
if(tree[root].rr - tree[root].ll == 1) {
// tree[root].cover = 0;
return;
}
update(root*2 , ll, rr, cover);
update(root*2+1 ,ll, rr, cover);
}
int query(int root, int ll, int rr){
if(tree[root].rr<=ll || tree[root].ll>= rr) return 0;
if(tree[root].ll>=ll && tree[root].rr <= rr && tree[root].cover >0){
return tree[root].rr-tree[root].ll;
}
if(tree[root].rr - tree[root].ll == 1) return 0;
int ans =0;
ans += query(root *2, ll, rr);
ans += query(root*2+1, ll, rr);
return ans;
}
int main(){
scanf("%d",&N);
int j=0;
int kk=0;
while(N--){
memset(tree,0,sizeof(tree));
for(int i=0;i<3;i++){
int lx,ly,rx,ry;
scanf("%d%d%d%d",&lx,&ly,&rx,&ry);
x_ind[++j] = lx;
x_ind[++j] = rx;
lines[++kk] = line(lx,rx,ly,1);
lines[++kk] = line(lx,rx,ry,-1);
}
sort(x_ind+1,x_ind+j+1);
sort(lines+1,lines+kk+1);
int q=1;
for(int i=1;i<=j;i++){
if(x_ind[q] !=x_ind[i])
x_ind[++q] = x_ind[i];
}
x_ind[0] = q;
create(1,1,q);
int ans =0;
for(int i=1;i<kk;i++){
update(1, lines[i].ll,lines[i].rr,lines[i].c);
int cover = query(1,x_ind[1],x_ind[q]);
ans += cover*(lines[i+1].h -lines[i].h);
}
printf("%d\n",ans);
}
return 0;
}