[TJOI2010]被污染的河流

题目背景
有一座城市,城市里有许多条人工河,河流的流向都是水平或者竖直的。为了方便市民用水,政府将河流设计成网格状。在水平方向上和竖直方向上,相邻河流的距离都是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;
}
发布了438 篇原创文章 · 获赞 234 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_43826249/article/details/104011303