오늘의 알고리즘

[C++] 백준 2568 전깃줄 2

하늘하늘 . 2022. 12. 19. 20:45
#include <iostream>
#include <algorithm>
#include <vector>
 
int n = 0;
std::vector<std::pair<int, int>> pair = {};
std::vector<int> vec = {};
int ansreverse[100001] = {};
 
int main() 
{	
	std::cin >> n;
	for (int i = 0; i < n; ++i) 
	{
		int A = 0;
		int B = 0;
		std::cin >> A >> B;
		pair.push_back({ A,B });
	}
 
	std::sort(pair.begin(), pair.end());
 
	int temp = 0;
 
	for (int i = 0; i < pair.size(); ++i)
	{
		if (vec.empty())
		{
			vec.push_back(pair[i].second);
			ansreverse[i] = 1;
		}
 
		else
		{
			if (vec[vec.size() - 1] < pair[i].second)
			{
				vec.push_back(pair[i].second);
				ansreverse[i] = vec.size();
			}
 
			else
			{
				auto iter = std::lower_bound(vec.begin(), vec.end(), pair[i].second);
				*iter = pair[i].second;
				ansreverse[i] = iter - vec.begin() + 1;
			}
		}
 
		if (ansreverse[i] > temp)
		{
			temp = ansreverse[i];
		}
	}
 
	std::cout << pair.size() - vec.size() << "\n";
 
	int index = vec.size();
	std::vector<int> ans = {};
	for (int i = n - 1; i >= 0; --i)
	{
		if (ansreverse[i] != index)
		{
			ans.push_back(pair[i].first);
		}
 
		else
			--index;
	}
 
	for (int i = ans.size() - 1; i >= 0; --i)
	{
		std::cout << ans[i] << "\n";
	}
 
	return 0;
}
 

이전에 풀어본 가장 긴 증가하는 부분 수열과 비슷합니다.

증가하는 수열과 비슷하기에 lower_bound를 사용해서 본인보다 초과한 자리 앞을 구해서 바꿔치는데,

그 때 본인의 순서를 기억합니다. 가장 앞쪽이라면 1, 맨 뒤라면 n입니다.

그렇게 되면 순서를 알 수 있기 때문에 순서에 맞지 않는 것들만 ans로 넣어주고 뒤로부터 출력합니다.