USACO 2023 February Contest Silver Division - Cow-libi#
Problem link: here
Solution Author: Stefan Dascalescu
Problem Solution#
Given that only one cow can reach all the grazings, we can conclude that if a cow can reach the grazing before and after (if such a cow exists), then it can reach all grazings.
Therefore, we sort the grazings by the time and for every alibi we binary search the two closest grazings to it and check if we can reach them. If this can happen, then the cow is not innocent.
Source code#
The source code in C++ can be seen below.
#include <bits/stdc++.h>
#define int long long
using namespace std;
struct event {
int x;
int y;
int time;
};
event grazing[100001];
event alibi[100001];
bool cmp(event a, event b) {
return a.time < b.time;
}
unsigned long long mysqrt(unsigned long long x) {
if (x == 0)
return 0;
unsigned long long rez = sqrt(x) - 1;
while (rez * rez < x)
rez++;
return rez;
}
bool possible(event a, event b) {
if (1ULL * (1ULL * mysqrt(1ULL * (1ULL * abs(a.x - b.x) * 1ULL * abs(a.x - b.x) + 1ULL * abs(a.y - b.y) * 1ULL * abs(a.y - b.y)))) <= 1ULL * abs(a.time - b.time))
return 1;
return 0;
}
signed main() {
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int g, n, i, j, might, r, pas;
cin >> g >> n;
for (i = 1; i <= g; i++) {
cin >> grazing[i].x >> grazing[i].y >> grazing[i].time;
}
for (i = 1; i <= n; i++) {
cin >> alibi[i].x >> alibi[i].y >> alibi[i].time;
}
sort(grazing + 1, grazing + 1 + g, cmp);
might = 0;
for (i = 1; i <= n; i++) {
r = 0;
pas = (1 << 16);
while (pas) {
if (r + pas <= g && grazing[r + pas].time <= alibi[i].time)
r += pas;
pas = pas / 2;
}
event a, b;
a = alibi[i];
b = grazing[r];
if (r == 0) {
r++;
a = alibi[i];
b = grazing[r];
if (possible(a, b))
might++;
}
else
if (possible(a, b)) {
if (r != n) {
b = grazing[r + 1];
if (possible(a, b)) might++;
} else
might++;
}
}
cout << n - might;
}