2020牛客国庆集训派对day1 D
Deep800080
https://ac.nowcoder.com/acm/contest/7817/D
分析
要求我们在一条直线上确定一个点。要求它覆盖的点最多。我们可以转换一下,对于每个点我们可以覆盖到它的地方有哪些。如此我们发现这些地方,一定在直线上构成一个线段,或者没有交点。那么我们就可以求出这个范围,然后通过差分就可以求出最多被覆盖的区间。这个我们可以通过勾股定理来求。但是我们最后得到的是一个数值。而有可能在直线的后方相交。为了得到有向距离,我们还要用叉积来判断正负。
- 要注意因为不能漏掉恰好重合的端点,所以我们要把差分的正负反一下。
- 用的的公式 和 ,结合代码食用更佳。
代码
#include<bits/stdc++.h> using namespace std; #define pii pair<double,long long> long long n;double R,A,B; const int N = 2e6 + 100; struct Node{double x,y;}a[N]; vector<pii> v; bool pd(int i) { double l = -B,r = A; double clac = l * a[i].y - a[i].x * r; return clac < 0; } int main() { scanf("%lld%lf%lf%lf",&n,&R,&A,&B); for(int i = 1;i <= n;i++) { scanf("%lf%lf",&a[i].x,&a[i].y); double X = a[i].x * a[i].x + a[i].y * a[i].y; double Y = A * A + B * B; double I = (B * a[i].x - A * a[i].y) * (B * a[i].x - A * a[i].y); if(I - R * R * Y > 1e-8) continue; double len1 = ((pd(i))?-1:1)*sqrt(X - I / Y) - ((R * R - I / Y)>1e-8 ? sqrt(R * R - I / Y) : 0.0); double len2 = ((pd(i))?-1:1)*sqrt(X - I / Y) + ((R * R - I / Y)>1e-8 ? sqrt(R * R - I / Y) : 0.0); v.push_back(pii(len1,-1));v.push_back(pii(len2,1)); } sort(v.begin(),v.end());int ans = 0,last = 0; for(auto x:v) {ans = max(ans,last -= x.second);} cout << ans << endl;return 0; }
比赛题解 文章被收录于专栏
近期比赛的题解应该有吧。。。