Editorial for Variadart
Submitting an official solution before solving the problem yourself is a bannable offence.
Author:
In this problem, we need to count the amount of darts within some radius of the origin, with the darts falling at different positions. Firstly, looping over every point and counting for every query will be too slow, we need a faster approach.
You can notice that the only thing that matters is this distance from origin, or radius, so the problem reduces to a single dimension. One way to solve this problem is to calculate the squared distance from origin of each point using Pythagoras' (i.e. ) and store them in a vector. Then, after receiving all dart inputs, we can sort that vector. This will allow us to do binary search on it with each radius query (squared) and use the index to get the number of elements with a smaller radius (closer to origin, or inside the circle). This gives us a time complexity of
for sorting followed by
binary searching, and a space complexity of
for storing the radius vector.
The reason we should work with the square of the radius is to avoid working with floating-point numbers. In order to find the exact distance from the origin for each point, we would need to do a square-root, producing a float. Points can be at arbitrary distances from the origin, and floats are not perfectly accurate. This could result in some point that is i.e. units from the origin being put into a float that can't represent it exactly, rounding to i.e.
, which is now outside of the circle with radius
. In this problem, so long as you use
double
, you won't encounter this issue, and indeed you can use them to construct a more efficient solution here. You can make an array
long storing the amount of points with a given distance from the origin (rounding up after doing the square root), and then do a cumulative sum of the array to make it so each value represents the amount of points at that distance or closer. Then, the queries each require just accessing an index of the array. However, when using the perfectly precise integer types, the squared radius could go up to a much larger number, and this solution is not generally correct due to floating point precision, so the above binary search solution is more applicable.
C++ solution:
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> radii;
int x,y;
while (n--) {
cin >> x >> y;
radii.push_back(x*x+y*y);
}
sort(radii.begin(), radii.end());
int m;
cin >> m;
int r;
while (m--) {
cin >> r;
cout << upper_bound(radii.begin(), radii.end(), r*r)-radii.begin() << endl;
}
}
Python solution:
from bisect import bisect_right
n = int(input())
radii = sorted([x*x+y*y for (x,y) in [map(int,input().split()) for _ in range(n)]])
m = int(input())
print("\n".join(map(lambda r: str(bisect_right(radii,r*r)), [int(input()) for _ in range(m)])))
Comments