CF2074D Counting Points 题解
这个题注意到数据范围:\(\sum_{i=1}^n r_i = m\)和 \(1 \le n \le m \le 2\cdot 10^5\)
数据范围并不是很大,所以说可以考虑枚举。
但是存在一个问题,题目中的整点个数怎么求?
我们可以对圆的公式进行一下变换:
对于某个以\((x_i,0)\)为圆心,以\(r_i\)为半径的圆,其边界和内部的点必然满足:
\[(x-x_i)^2+y^2\leq r_i^2
\]
进行如下的转换:
\[y^2 \le r_i^2-(x-x_i)^2\iff-\sqrt{r_i^2-(x-x_i)^2} \le y \le \sqrt{r_i^2-(x-x_i)^2}
\]
也就是说,对于一个圆内部的某个横坐标为\(x\)的点,它的\(y\)值一定在\(-\sqrt{r_i^2-(x-x_i)^2} \le y \le \sqrt{r_i^2-(x-x_i)^2}\)这个范围上,所以说这个横坐标为\(x\)的点在该圆及其内部的点共有\(2\left \lfloor {\sqrt{r_i^2-(x-x_i)^2}} \right \rfloor +1\)个
现在还有一个问题,如果题目中的两两不相交那么就很容易计算出来了,但是,有多个圆相交了怎么办?只需要记录一下每个横坐标能取到的最大值就可以了。
记录最大值用std::map就可以了
总之,我们需要用map记录下每个圆内部的每个横坐标\(x\)对应的y的整数数量并取最大值,然后遍历一遍map即可
代码
#include <bits/stdc++.h>
using namespace std;
/*
*/
#define ll long long
// #define double long double
// #define double eps=1e-9;
void sol() {
int n,m;
cin>>n>>m;
vector<ll> x(n),r(n);
for(int i=0;i<n;i++) cin>>x[i];
map<ll,ll> mp;
for(int i=0;i<n;i++){
cin>>r[i];
for(int cur=x[i]-r[i];cur<=x[i]+r[i];cur++){
mp[cur]=max(mp[cur],(ll)floor(sqrt(r[i]*r[i]-(cur-x[i])*(cur-x[i]))));
}
}
ll ans=0;
for(auto [key,val]:mp){
ans+=(2*val+1);
}
cout<<ans<<'\n';
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--) {
sol();
}
return 0;
}
总结:数据范围不大可以考虑枚举,计算整点数量可以固定一维然后用另一维坐标下取整计算

浙公网安备 33010602011771号