BOJ 27847 - Cow-libi

image.png

USACO를 너무 오랜만에 손대다보니 문제를 제대로 해석하는 것조차 쉽지가 않다.

이벤트를 시간순으로 정렬할 때, 어떤 소가 $(x,y,t)$ 에 있었다면 $t$에 가장 가까운 이벤트 두개만 보고 그 이벤트에 도달 가능한지를 판단해주면 된다.

이분 탐색으로 찾아주자

왜냐면 $G$개의 입력 자체가 연속해서 이동할 수 있음이 보장되기 때문에 그 두개에만 제대로 갈 수 있어도 나머지 것들은 무조건 갈 수 있기 때문이다.

그 이벤트 두개에 도달 가능한 소는 innocent하지 않으므로 이 소들의 수를 세서 $N$에서 빼준 것이 정답이다.

void solve() {  
   int G, N;  
   cin >> G >> N;  
  
   vector<array<int, 3>> event;  
   for (int i = 0; i < G; i++) {  
      int x, y, t;  
      cin >> x >> y >> t;  
      event.pb({t, x, y});  
   }  
   sort(all(event));  
   for (int i = 0; i < G - 1; i++) {  
      if (event[i][0] == event[i + 1][0]) {  
         assert(event[i][1] == event[i + 1][1] && event[i + 1][2] == event[i][2]);  
      }  
   }  
  
   int ans = 0;  
   for (int i = 0; i < N; i++) {  
      int x, y, t;  
      cin >> x >> y >> t;  
  
      auto can = [&](int j) -> bool {  
         if (j < 0 || j >= G) return true;  
         int x_diff = (x - event[j][1]);  
         int y_diff = (y - event[j][2]);  
         int dist_diff = x_diff * x_diff + y_diff * y_diff;  
         int time_diff = abs(event[j][0] - t);  
         return dist_diff <= time_diff * time_diff;  
      };  
  
      const int inf = 1e9 + 1;  
      array<int, 3> key{int(t), inf, inf};  
      int j = ubi(event, key);  
      bool c = 1;  
      if (can(0) && can(j) && can(j - 1)) {  
         ans++;  
         debug(i);  
      }  
   }  
   cout << N - ans;  
}

Tags:

Categories:

Updated:

Comments