문제 링크: https://www.acmicpc.net/problem/11003
딱봐도 뭔가 슬라이딩 윈도우 같습니다. 근데 N, L 범위가 크기 때문에 구현 방법을 좀 생각해봐야 합니다.
큐, 링크드리스트, 벡터를 쓴다? 윈도우가 한 칸 움직일 때마다 배열 전체를 뒤져봐야 합니다. 큐는 아시겠지만 iterator도 없습니다
힙을 쓴다? min값을 O(1)에 찾을 수 있는건 좋습니다. 그런데 std::priority_queue
에는 top에만 접근할 수 있고 다른 값에 접근을 못해 힙에서 원하는 값을 뺄 수 없습니다.
풀이 중 하나는 덱(std::deque
)을 사용하는 겁니다.
덱 내부가 인덱스, 값 모두 오름차순으로 정렬되도록 유지하고, 윈도우 크기가 L일 때 한 칸 움직이면 i-L번째 원소를 뺍니다.
인덱스, 값 모두 오름차순으로 정렬하는 방법은 간단합니다. 덱에 원소를 뒤에 넣을 때, 그 원소보다 큰 원소가 있으면 빼버리는 겁니다.
예를 들어 Fig 1.의 Iteration 3을 보면 덱에 {1, 5}가 들어가 있고, 2를 넣어야 하는데 덱 맨 뒤에 5가 있으니 5를 뺍니다. 그러면 덱이 {1}이 되는데 1은 2보다 작으니 그냥 넣으면 덱이 {1, 2}가 됩니다.
그 다음 Iteration 4를 보면 먼저 0번째 원소인 1을 덱에서 제거합니다. 여기서 1이 0번째 원소라는걸 알기 위해서는 덱에 값과 인덱스를 함께 넣어야 하겠죠. 3을 덱에 넣는 과정은 Iteration 3과 동일합니다
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int N, L;
cin >> N >> L;
vector<int> arr(N);
for (auto& c : arr)
cin >> c;
deque<pair<int, int>> dq; // (value, idx), 오름차순
for (int i = 0; i < N; ++i) {
if (!dq.empty() && dq.front().second <= i - L)
dq.pop_front();
// arr[i]가 가장 큰 값이 되도록 만듦
while (!dq.empty() && dq.back().first > arr[i])
dq.pop_back();
dq.emplace_back(arr[i], i);
cout << dq.front().first << ' ';
}
return 0;
}
이렇게 푸니 대충 1.4초정도 걸립니다. 입출력에 시간이 많이 들어가나봅니다.
'Online Judge > 백준' 카테고리의 다른 글
[백준][C++] 5463: 건포도 (0) | 2020.08.06 |
---|---|
[백준][C++] 11051: 이항 계수 2 (0) | 2020.08.05 |
[백준][C++] 5893: 17배 (0) | 2020.08.03 |
[백준][C++] 4485: 녹색 옷 입은 애가 젤다지? (0) | 2020.08.03 |
[백준][C++] 11779: 최소비용 구하기 2 (0) | 2020.08.02 |