Boxing Game Score
National Olympiad — Regional round (2016 season)
Submission name: game.cpp
Problem summary
For each hit, count across M marked points how many of N disks lie entirely inside the circle centered at that point with the hit radius. Starting with the second hit, double its supplied radius if the preceding hit earned an even number of points. Sum all hit scores.
Input
N M Q; N lines cx cy r; M lines x y; Q strengths.
Output
The final total score.
Constraints
1 ≤ N,Q ≤ 10000; 1 ≤ M ≤ 10; coordinates, radii and strengths are between 1 and 10000. All centers are distinct. Scoring circles are guaranteed not internally tangent to input disks.
Worked example
Official sample; other valid outputs may exist.
Input
4 1 3 2 2 1 3 5 2 6 2 3 8 8 1 4 4 4 3 3
Output
5
Solution analysis
- A disk of radius r whose center is distance D from a marked point lies inside a scoring circle of radius s exactly when D+r<s. Precompute this threshold for each of the NM point-disk pairs.
- Sort all thresholds together. The score of a hit with effective radius s is the number of thresholds strictly below s, obtained with lower_bound. Remember only the score of the immediately preceding hit to decide doubling.
- In the sample radius 4 earns 2. Because this is even, the next strength 3 becomes radius 6 and earns 3. The last hit remains radius 3 and earns zero, for total 5.
Why it works
Each point-disk pair contributes one exactly when its containment threshold is below the effective radius. Sorted threshold counting therefore gives the exact hit score. Induction over hits shows that using the preceding score chooses the correct radius each time, so summing those scores yields the final result.
Watch out. Containment concerns the entire disk, not just its center. The first hit is never doubled; parity refers to the previous hit, not the cumulative total.
Commented C++17 solution
An independently written complete program with standard headers.
// Key idea: Each point-disk pair contributes one exactly when its containment threshold is below the
// effective radius. Sorted threshold counting therefore gives the exact hit score.
#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;
struct Disk{
long long x,y,radius;
};
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n,m,q;
cin>>n>>m>>q;
vector<Disk>disks(n);
for(Disk&disk:disks){
cin>>disk.x>>disk.y>>disk.radius;
}
vector<long double>thresholds;
thresholds.reserve(n*m);
for(int i=0;i<m;++i){
long long x,y;
cin>>x>>y;
for(Disk disk:disks){
long long dx=x-disk.x,dy=y-disk.y;
thresholds.push_back(sqrtl(dx*dx+dy*dy)+disk.radius);
}
}
sort(thresholds.begin(),thresholds.end());
long long total=0,previous=0;
for(int i=0;i<q;++i){
int strength;
cin>>strength;
int radius=strength;
if(i>0&&previous%2==0){
radius*=2;
}
previous=lower_bound(thresholds.begin(),thresholds.end(),static_cast<long double>(radius))-
thresholds.begin();
total+=previous;
}
cout<<total<<'\n';
}