본문 바로가기
알고리즘/백준

[백준] 3078 좋은 친구 c++

by 오오오니 2023. 1. 7.

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

 

3078번: 좋은 친구

첫째 줄에 N과 K가 주어진다. (3 ≤ N ≤ 300,000, 1 ≤ K ≤ N) 다음 N개 줄에는 상근이네 반 학생의 이름이 성적순으로 주어진다. 이름은 알파벳 대문자로 이루어져 있고, 2글자 ~ 20글자이다.

www.acmicpc.net

 

정답률 29%인데 한번에 맞춰서 기분이 너무 너무 좋았다 💞  💞 💞 💞 💞 💞 💞 💞 💞

처음에 문제 봤을때 떠오른 생각은 뒤에 있는 k명하고 길이를 비교하는 것을 생각했는데

골드 4가 그렇게 쉬울리가 없고 정답률이 낮아서 그 방법은 아닐 것 같았다. 시간제한 1초이기도 했고.

풀이

*큐에는 k+1개를 담을 수 있다. 비교할 등수 범위를 정해준다.

*배열 nameLength에는 해당 범위내(k+1)에 길이가 몇개씩 있는지 체크해준다. 

  ex) 현재 큐에  5가 2개 6이 1개 7이 1개가 있다면 배열의 상태는 아래 그림과 같다.

1.i 번째 친구의 이름의 길이를 큐에 담아준다. 

2.큐의 사이즈가 k+2개가 되면 큐를 pop해주고 배열에 해당하는 부분도 크기를 감소한다.

3. nameLength[nameSize]를 증가시켜준다. (새로 들어온 이름)

4. 현재 큐에 들어 있는 같은 nameSize와 각각 한 쌍을 이룰 수 있으므로   

 nameLength[nameSize]-1(자기자신 제외 )를 ans에 더해준다.

ex) 예제 1에서 큐에 3, 3이 들어있고 새로운 3이 들어오면 큐는 3,3,3이 들어있고  nameLength[3]=3이 된다.

새로운 2쌍이  생긴다. ->  (1번째 3,3번쨰 3) ,(2번째 3, 3번째 3)

4번째 친구의 이름의 길이가 3일때  큐에는 3개까지 담을 수 있으므로 앞에 3이 빠지고 새로운 3이 들어가서 

큐 : 3, 3, 3 배열 :  nameLength[3]=3  이 되고 ans에 2를 더해준다.ans +=nameLength[3]-1 

#include<iostream>
#include<queue>
#include<string>

using namespace std;


queue<int>name;
int nameLength[21];
int N, K;
string temp;
int nameSize;
long long ans;
int main()
{
	cin >> N >> K;
	for (int i = 0; i < N; i++)
	{
		cin >> temp;
		nameSize = temp.length();
		name.push(nameSize);
		
		if (i > K)//큐에 k+2개 이상 담기게 되면 nameLength의 수를 하나 감소하고 큐를 pop해준다. 
		{
			if (nameLength[name.front()] > 0)
				nameLength[name.front()]--;
			name.pop();

		}
		
		nameLength[nameSize]++;
		if (nameLength[nameSize] > 0)
			ans+= (nameLength[nameSize]-1);
	
	}

	cout << ans;
}

'알고리즘 > 백준' 카테고리의 다른 글

[백준] 11404 플로이드 C++  (0) 2023.03.24
[백준] 1715 카드 정렬하기 c++  (1) 2023.01.28
[백준] 3980 선발 명단 c++  (0) 2023.01.07
[백준] 22252 정보 상인 호석 c++  (0) 2023.01.05
[백준] 17829 222-풀링 c++  (0) 2023.01.05