题目背景
有一座城市,城市里有许多条人工河,河流的流向都是水平或者竖直的。为了方便市民用水,政府将河流设计成网格状。在水平方向上和竖直方向上,相邻河流的距离都是1公里。河流围出许多格子,每个格子就是一个社区,社区里的居民可以到社区周边四条河段中的任意一处打水喝。
题目描述
郁闷的是,不久之后,有些不法商人修建了工厂,污染了河流。河边许多居民喝了被污染的水,生病了。政府派出专员小强调查污染情况。地理专家小强行动迅速,很快给出了污染分布。他给出了一张污染清单。清单列出了被污染的河段,所有能喝到该河段水的居民都有可能生病(河段的端点处忽略不计)。但是,笨笨的小强怎么也算不出具体会有多少个社区的居民会生病,所以,他请你来帮帮忙。
输入格式
输入文件的第一行是一个整数N,表示被污染的河段的数目。
接下来N行,每行4个整数x1,y1,x2,y2,表示被污染河段的起始位置和结束位置。每行输入的两个位置保证不重合,并且满足x1=x2或y1=y2
输出格式
输出一个整数A,表示有A个社区的居民会喝到被污染的水。
输入输出样例
输入 #1复制
3
1 3 4 3
6 7 6 3
4 6 7 6
输出 #1复制
16
说明/提示
对于10%的数据,1 ≤ x1,y1,x2,y2 ≤ 100,N ≤ 100;
对于30%的数据,1 ≤ x1,y1,x2,y2 ≤ 10000,N ≤ 100;
对于100%的数据,1 ≤ x1,y1,x2,y2 ≤ 100000,N ≤ 10000。
每个测试点时限1秒。
看似很难维护。
但是我们如果把一条线想象为一个小矩形呢?很裸的矩形面积并的问题。
所以我们做一下扫描线即可。
AC代码:
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10;
int n,m=1e5+2;
struct node{int l,r,h,f;}; vector<node> v;
int cmp(node a,node b){return a.h<b.h;}
int t[N<<2],lazy[N<<2];
void change(int p,int l,int r,int ql,int qr,int v){
if(l==ql&&qr==r){
lazy[p]+=v;
if(lazy[p]) t[p]=r-l+1; else t[p]=t[p<<1]+t[p<<1|1];
return ;
}
int mid=l+r>>1;
if(qr<=mid) change(p<<1,l,mid,ql,qr,v);
else if(ql>mid) change(p<<1|1,mid+1,r,ql,qr,v);
else change(p<<1,l,mid,ql,mid,v),change(p<<1|1,mid+1,r,mid+1,qr,v);
if(lazy[p]) t[p]=r-l+1;
else t[p]=t[p<<1]+t[p<<1|1];
}
inline int solve(){
int res=0;
change(1,0,m,v[0].l,v[0].r-1,1);
for(int i=1;i<v.size();i++){
res+=t[1]*(v[i].h-v[i-1].h);
change(1,0,m,v[i].l,v[i].r-1,v[i].f);
}
return res;
}
signed main(){
cin>>n;
for(int i=1;i<=n;i++){
int x1,x2,y1,y2; cin>>x1>>y1>>x2>>y2;
if(x1==x2){
if(y1>y2) swap(y1,y2);
v.push_back({x1-1,x1+1,y1,1}); v.push_back({x1-1,x1+1,y2,-1});
}else{
if(x1>x2) swap(x1,x2);
v.push_back({x1,x2,y1-1,1}); v.push_back({x1,x2,y1+1,-1});
}
}
sort(v.begin(),v.end(),cmp);
printf("%d\n",solve());
return 0;
}