※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 18266번 문제인 Meetings이다.
문제는 아래 링크를 확인하자.

https://www.acmicpc.net/problem/18266 

 

18266번: Meetings

Two barns are located at positions $0$ and $L$ $(1\le L\le 10^9)$ on a one-dimensional number line. There are also $N$ cows $(1\le N\le 5\cdot 10^4)$ at distinct locations on this number line (think of the barns and cows effectively as points). Each cow $i

www.acmicpc.net

소들의 번호를 생각하지 않고 시간의 흐름에 따른 소의 위치가 어떻게 되는지만을 생각하면 소들의 움직임은 각 소가 처음 보고 있는 방향으로 (다른 소와의 만남에 상관없이) 계속 직진하는 모습과 같다는 점을 관찰하자. 잘 이해가 안된다면 두 소가 만나서 서로 뒤돌아 움직이는 모습과 두 소가 만나고 그대로 지나가는 모습은 번호를 떼고 보면 똑같아보이는 점을 생각해보자.

 

위의 관찰을 이용하면 왼쪽 헛간과 오른쪽 헛간에 (몇번 소인지는 몰라도) 각각 소가 들어오는 시각이 언제일지를 빠르게 구해낼 수 있다.

 

한편, 두 헛간 사이에 있는 소들 중 소 하나가 다음으로 헛간에 들어간다면 그 소는 맨 왼쪽의 소 또는 맨 오른쪽의 소가 될 수밖에 없음을 관찰하자. 중간에 있는 소가 순서를 바꿔 헛간으로 들어갈 수는 없기 때문이다. 이와 먼젓번에서 구한 각 헛간에 소가 들어오는 시각을 이용하면 소들이 헛간에 들어가는 순서를 시간순으로 알 수 있다. 이를 이용해 T값을 구해내자.

 

한편, 좌표 x, y에 있는 두 소가 시간 T 이하에 만난다는 것은 x<y이며 x에 있는 소는 오른쪽을 보고 y에 있는 소는 왼쪽을 바라보고 x+T >= y-T를 만족한다는 것과 같다. 이러한 관계를 만족하는 쌍의 수는 각 소들을 좌표 오름차순으로 살펴보면서 오른쪽을 살펴보고 있는 소들이 들어있는 monotone queue를 관리하는 것으로 빠르게 구해낼 수 있다.

 

아래는 제출한 소스코드이다.

#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
typedef long long ll;

int N; ll L, T;
int arr[50000];
int wgt[50000], total;
ll pos[50000];
int dir[50000];
queue<int> dirque;
ll dist[50000];
int psum, lll, rrr;

ll ans;

bool compD(int& x1, int& x2) {
	return dist[x1] < dist[x2];
}

bool compP(int& x1, int& x2) {
	return pos[x1] < pos[x2];
}

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);

	cin >> N >> L;

	for (int i = 0; i < N; i++) {
		arr[i] = i;
		cin >> wgt[i] >> pos[i] >> dir[i];
		total += wgt[i];
		if (dir[i] > 0) dist[i] = L - pos[i];
		else dist[i] = pos[i];
	}
	total = (total + 1) / 2;
	
	sort(arr, arr + N, compD);

	for (int i = 0; i < N; i++) {
		int& idx = arr[i];
		dirque.push(dir[idx]);
	}

	sort(arr, arr + N, compP);

	lll = 0, rrr = N - 1;
	while (psum < total) {
		if (dirque.front() < 0) {
			int& idx = arr[lll];
			psum += wgt[idx];
			lll++;
		}
		else {
			int& idx = arr[rrr];
			psum += wgt[idx];
			rrr--;
		}
		dirque.pop();
	}

	sort(arr, arr + N, compD);

	T = dist[arr[lll + (N - 1 - rrr) - 1]] * 2;

	sort(arr, arr + N, compP);

	queue<ll> que;
	for (int i = 0; i < N; i++) {
		int& idx = arr[i];
		if (dir[idx] > 0) que.push(pos[idx]);
		else {
			while ((!que.empty()) && que.front() + T < pos[idx]) que.pop();
			ans += que.size();
		}
	}

	cout << ans;
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 11999 // C++] Milk Pails (Bronze)  (1) 2023.10.12
[BOJ 18265 // C++] MooBuzz  (0) 2023.10.11
[BOJ 18267 // C++] Milk Visits  (0) 2023.10.09
[BOJ 3188 // C++] nule  (0) 2023.10.08
[BOJ 3185 // C++] kviz  (0) 2023.10.07

+ Recent posts