P6875 [COCI2013-2014#6] KRUŽNICE

洛谷

由样例可以知道,一个圆只贡献一个区域,而一个圆在中间被几个圆完全连接时会被分成两个部分,计算两个贡献。

那么我们很容易想到先按照左端点排序,在左端点相同时,比较半径大小。

然后从后向前连接,如果前面与当前点的左端相等,那么我们就可以通过这个圆尝试把前面的圆分成两部分。

然后记录下状态,如果前面刚好有一个圆的右端点,则直接连接,继承到当前位置。

如果发现此时的右端点与尝试分开的圆的右端点相等,那么就记录贡献。

代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,f[300005],ans;
map<int,int> mp;
struct P{
	int x,r;
}a[300005];
bool cmp(P a,P b){
	if(a.x-a.r==b.x-b.r)return a.r>b.r;
	return a.x-a.r<b.x-b.r;
}
signed main(){
	cin>>n;
	for(int i=1;i<=n;i++)cin>>a[i].x>>a[i].r;
	sort(a+1,a+n+1,cmp);
	for(int i=1;i<=n;i++){
		if(mp[a[i].x-a[i].r])f[i]=mp[a[i].x-a[i].r];
		if(i!=1){
			if(a[i].x-a[i].r==a[i-1].x-a[i-1].r)f[i]=i-1;
		}
		if(f[i]&&a[i].x+a[i].r==a[f[i]].x+a[f[i]].r)ans++,f[i]=0;
		if(f[i])mp[a[i].x+a[i].r]=f[i];
	}
	cout<<ans+n+1;
	return 0;
}
posted @ 2025-12-07 12:38  huhangqi  阅读(2)  评论(0)    收藏  举报