2531(회전 초밥)
유형 : 슬라이딩,, 그리디?
#define _CRT_SECURE_NO_WARNINGS
#include <string>
#include <vector>
#include <queue>
#include <memory.h>
#include <algorithm>
#include <iostream>
#include <stack>
#include <unordered_set>
#include <math.h>
using namespace std;
int belt[30001] = { 0 };
int check[3001] = { 0 };
int main(void)
{
cin.tie(NULL);
cout.tie(NULL);
ios_base::sync_with_stdio(false);
freopen("input.txt", "r", stdin);
int cnt = 0;
int answer = 0;
int g_answer = 0;
int pre_dish = -1;
int n, d, k, c;//접시의수, 초밥의 가짓수, 연속해서 먹는 접시의수, 쿠폰번호
cin >> n >> d >> k >> c;
for (int i = 0; i < n; i++)
{
cin >> belt[i];
if (cnt != k)
{
cnt++;
if (check[belt[i]] == 0 && belt[i] != c) // 선택되지 않은 음식이자, 쿠폰이아니면 엔서 증가
{
answer++;
g_answer = max(g_answer, answer);
}
check[belt[i]] += 1;
if (cnt == k) // 마지막 선택이면 없어질 음식 선택
pre_dish = belt[i - k + 1];
}
else
{
check[pre_dish] -= 1;
if (check[pre_dish] == 0 && pre_dish != c) // 쿠폰이랑 다른 음식이면 answer--
{
answer--;
}
if (check[belt[i]] == 0 && belt[i] != c) // 선택되지 않은 음식이자, 쿠폰이아니면 엔서 증가
{
answer++;
g_answer = max(g_answer, answer);
}
check[belt[i]] += 1;
pre_dish = belt[i - k + 1];
}
}
//1 <= belt[i] <= d
for (int i = 0; i < k; i++)
{
check[pre_dish] -= 1;
if (check[pre_dish] == 0 && pre_dish != c) // 쿠폰이랑 다른 음식이면 answer--
{
answer--;
}
if (check[belt[i]] == 0 && belt[i] != c) // 선택되지 않은 음식이자, 쿠폰이아니면 엔서 증가
{
answer++;
g_answer = max(g_answer, answer);
}
check[belt[i]] += 1;
int idx = i - k + 1;
if (idx < 0)
idx = n + idx;
pre_dish = belt[idx];
}
cout << g_answer + 1;
}
고찰
회전초밥에서 연속된 초밥에서 가장 많은 종류를 선택하는 경우의 수를 구하는 문제
여기에 쿠폰이라는 변수가 있어서 쿠폰에 있는 음식은 카운트 하지 않는다.
check 배열로 현재 어떤음식이 선택되어있는지 확인한다.
음식을 k개 선택했을 때 pre_dish 변수에 없어질 변수를 담는다.
속도를 빠르게 하기 위해 cin» 으로 인풋을 받으면서 한번 탐색을 하고
회전초밥이 원형이기 때문에 마지막으로 idx를 0부터 k까지 탐색한다.
deque를 쓰면 좀더 간단히 구현할 수 있을것 같다.