Koder / 박성훈
article thumbnail

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

 

2531번: 회전 초밥

첫 번째 줄에는 회전 초밥 벨트에 놓인 접시의 수 N, 초밥의 가짓수 d, 연속해서 먹는 접시의 수 k, 쿠폰 번호 c가 각각 하나의 빈 칸을 사이에 두고 주어진다. 단, 2 ≤ N ≤ 30,000, 2 ≤ d ≤ 3,000, 2 ≤

www.acmicpc.net

연속된 고정 길이의 회전초밥들을 골랐을때

+ 고정된 한개의 메뉴가 있을때,

초밥의 종류를 최대한 다양하게 가져가도록 하는 문제

 

15961번은 범위가 매우 크기 때문에 브루트포싱으로 해결할 수 없고,

회전초밥의 길이가 고정적이라는 점에서 착안해서

슬라이딩 윈도우 알고리즘을 적용해서 문제를 해결했다.

 

초밥의 종류를 관리하는데에는 다양한 방법이 있을 수 있는데,

일반적인 배열의 인덱스를 사용해서 관리할 수도 있겠지만

이러면 초밥의 종류를 셀 변수를 하나 더 선언해주거나

추가적인 시간이 필요하게 된다.

 

그래서 나는 unordered_map 에

index로 초밥의 종류,

value로 해당 초밥의 수

를 저장했고,

 

value 가 0이 되면 unordered_map::erase 를 이용해서

삭제 해준 뒤

전체 초밥의 종류는 unordered_map::size 를 이용해 구했다.

N범위가 커서 시간제한이 빡빡한 편인지

그냥 map으로 구현시 TLE를 받게 된다.

참고해야할듯.

 

#include <bits/stdc++.h>
using namespace std;

int N,D,K,C;
int sushi[3456789] = {0};
int ans = -1;

unordered_map<int,int> curr;

int idx(int k){
	return (k+N)%N;
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	
	cin >> N >> D >> K >> C;
	for(int i=0; i<N; i++){
		cin >> sushi[i];
	}
	
	for(int i=0; i<K; i++){ curr[sushi[i]]++; }
	ans = max(ans, (int)curr.size());
	curr[C]++;
	
	for(int i=K; i<N+K; i++){
		curr[sushi[idx(i)]]++;
		curr[sushi[idx(i-K)]]--;
		if(curr[sushi[idx(i-K)]] == 0){
			curr.erase(sushi[idx(i-K)]);
		}
		ans = max(ans, (int)curr.size());
	}
	cout << ans;
	return 0;
}

반응형