#include <array>
#include <iostream>
#include <queue>
#include <vector>
template <std::size_t N, typename It, typename Queue>
std::array<It, N> asArray(Queue& queue, It emptyValue)
{
std::array<It, N> res;
for (auto& e : res) {
if (queue.empty()) {
e = emptyValue;
} else {
e = queue.top();
queue.pop();
}
}
return res;
}
template <std::size_t N, typename It, typename ValueGetter>
std::array<It, N>
MinNElementsBy(It begin, It end, ValueGetter valueGetter)
{
auto myComp = [&](const It& lhs, const It& rhs){ return valueGetter(*lhs) < valueGetter(*rhs); };
std::priority_queue<It, std::vector<It>, decltype(myComp)> queue(myComp);
for (auto it = begin; it != end; ++it) {
queue.push(it);
if (N < queue.size()) {
queue.pop();
}
}
return asArray<N>(queue, end);
}
struct Point {
double x; double y;
};
std::ostream& operator << (std::ostream& os, const Point& p)
{
return os << "{" << p.x << ", " << p.y << "}";
}
double square(double x) { return x * x; }
double SqrDistance(const Point& p1, const Point& p2)
{
return square(p1.x - p2.x) + square(p1.y - p2.y);
}
int main ()
{
const std::vector<Point> points = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}};
const Point ref{42, 1};
auto its = MinNElementsBy<2>(points.begin(), points.end(), [&](const Point& p) { return SqrDistance(ref, p); });
for (auto it : its) {
std::cout << *it << " ";
}
}
I2luY2x1ZGUgPGFycmF5PgojaW5jbHVkZSA8aW9zdHJlYW0+CiNpbmNsdWRlIDxxdWV1ZT4KI2luY2x1ZGUgPHZlY3Rvcj4KCnRlbXBsYXRlIDxzdGQ6OnNpemVfdCBOLCB0eXBlbmFtZSBJdCwgdHlwZW5hbWUgUXVldWU+CnN0ZDo6YXJyYXk8SXQsIE4+IGFzQXJyYXkoUXVldWUmIHF1ZXVlLCBJdCBlbXB0eVZhbHVlKQp7CiAgICBzdGQ6OmFycmF5PEl0LCBOPiByZXM7CiAgICBmb3IgKGF1dG8mIGUgOiByZXMpIHsKICAgICAgICBpZiAocXVldWUuZW1wdHkoKSkgewogICAgICAgICAgICBlID0gZW1wdHlWYWx1ZTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBlID0gcXVldWUudG9wKCk7CiAgICAgICAgICAgIHF1ZXVlLnBvcCgpOwogICAgICAgIH0KICAgIH0KICAgIHJldHVybiByZXM7Cn0KCnRlbXBsYXRlIDxzdGQ6OnNpemVfdCBOLCB0eXBlbmFtZSBJdCwgdHlwZW5hbWUgVmFsdWVHZXR0ZXI+CnN0ZDo6YXJyYXk8SXQsIE4+Ck1pbk5FbGVtZW50c0J5KEl0IGJlZ2luLCBJdCBlbmQsIFZhbHVlR2V0dGVyIHZhbHVlR2V0dGVyKQp7CiAgICBhdXRvIG15Q29tcCA9IFsmXShjb25zdCBJdCYgbGhzLCBjb25zdCBJdCYgcmhzKXsgcmV0dXJuIHZhbHVlR2V0dGVyKCpsaHMpIDwgIHZhbHVlR2V0dGVyKCpyaHMpOyB9OwogICAgc3RkOjpwcmlvcml0eV9xdWV1ZTxJdCwgc3RkOjp2ZWN0b3I8SXQ+LCBkZWNsdHlwZShteUNvbXApPiBxdWV1ZShteUNvbXApOwogICAgCiAgICBmb3IgKGF1dG8gaXQgPSBiZWdpbjsgaXQgIT0gZW5kOyArK2l0KSB7CiAgICAgICAgcXVldWUucHVzaChpdCk7CiAgICAgICAgaWYgKE4gPCBxdWV1ZS5zaXplKCkpIHsKICAgICAgICAgICAgcXVldWUucG9wKCk7CiAgICAgICAgfQogICAgfQogICAgcmV0dXJuIGFzQXJyYXk8Tj4ocXVldWUsIGVuZCk7Cn0KCnN0cnVjdCBQb2ludCB7CiAgICBkb3VibGUgeDsgZG91YmxlIHk7Cn07CgpzdGQ6Om9zdHJlYW0mIG9wZXJhdG9yIDw8IChzdGQ6Om9zdHJlYW0mIG9zLCBjb25zdCBQb2ludCYgcCkKewogICAgcmV0dXJuIG9zIDw8ICJ7IiA8PCBwLnggPDwgIiwgIiA8PCBwLnkgPDwgIn0iOwp9Cgpkb3VibGUgc3F1YXJlKGRvdWJsZSB4KSB7IHJldHVybiB4ICogeDsgfQoKZG91YmxlIFNxckRpc3RhbmNlKGNvbnN0IFBvaW50JiBwMSwgY29uc3QgUG9pbnQmIHAyKQp7CiAgICByZXR1cm4gc3F1YXJlKHAxLnggLSBwMi54KSArIHNxdWFyZShwMS55IC0gcDIueSk7Cn0KCmludCBtYWluICgpCnsKICAgIGNvbnN0IHN0ZDo6dmVjdG9yPFBvaW50PiBwb2ludHMgPSB7ezAsIDF9LCB7MSwgMH0sIHstMSwgMH0sIHswLCAtMX19OwogICAgY29uc3QgUG9pbnQgcmVmezQyLCAxfTsKICAgIAogICAgYXV0byBpdHMgPSBNaW5ORWxlbWVudHNCeTwyPihwb2ludHMuYmVnaW4oKSwgcG9pbnRzLmVuZCgpLCBbJl0oY29uc3QgUG9pbnQmIHApIHsgcmV0dXJuIFNxckRpc3RhbmNlKHJlZiwgcCk7IH0pOwoKICAgIGZvciAoYXV0byBpdCA6IGl0cykgewogICAgICAgIHN0ZDo6Y291dCA8PCAqaXQgPDwgIiAiOyAgIAogICAgfQp9Cg==