[백준 10816] 숫자 카드 2 (C#, C++) - soo:bak
작성일 :
문제 링크
설명
숫자 카드의 개수를 효율적으로 계산하는 문제입니다.
문제 이해
- 상근이가 가진 숫자 카드의 개수
N
과 카드에 적힌N
개의 숫자가 주어집니다. - 숫자 카드의 개수를 확인해야 할 숫자
M
과 그M
개의 숫자가 주어집니다. - 각 숫자에 대해, 상근이가 몇 개의 카드를 가지고 있는지 구해야 합니다.
접근법
- 이분 탐색을 사용하여 효율적으로 각 숫자의 개수를 구합니다.
- 먼저 상근이가 가진 숫자 카드를 정렬합니다.
- 확인할 숫자에 대해 이분 탐색으로 좌측 경계(left bound)와 우측 경계(right bound)를 찾아 개수를 계산합니다.
예제 시뮬레이션
입력:
1
2
3
4
10
6 3 2 10 10 10 -10 -10 7 3
8
10 9 -5 2 3 4 5 -10
과정:
- 상근이가 가진 숫자 카드를 정렬하면
[-10, -10, 2, 3, 3, 6, 7, 10, 10, 10]
이 됩니다. - 확인할 숫자에 대해 좌측 경계와 우측 경계를 찾아 개수를 계산합니다.
10
의 개수:3
9
의 개수:0
-5
의 개수:0
2
의 개수:1
3
의 개수:2
4
의 개수:0
5
의 개수:0
-10
의 개수:2
결과는 3 0 0 1 2 0 0 2
입니다.
Code
[ C# ]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
namespace Solution {
class Program {
static void Main(string[] args) {
int n = int.Parse(Console.ReadLine()!);
var cards = Console.ReadLine()!
.Split()
.Select(int.Parse)
.OrderBy(x => x)
.ToArray();
int m = int.Parse(Console.ReadLine()!);
var nums = Console.ReadLine()!.Split().Select(int.Parse);
var result = new List<int>();
foreach (var num in nums) {
int left = LowerBound(cards, num);
int right = UpperBound(cards, num);
result.Add(right - left);
}
Console.WriteLine(string.Join(" ", result));
}
static int LowerBound(int[] arr, int target) {
int low = 0, high = arr.Length;
while (low < high) {
int mid = (low + high) / 2;
if (arr[mid] >= target) high = mid;
else low = mid + 1;
}
return low;
}
static int UpperBound(int[] arr, int target) {
int low = 0, high = arr.Length;
while (low < high) {
int mid = (low + high) / 2;
if (arr[mid] > target) high = mid;
else low = mid + 1;
}
return low;
}
}
}
[ C++ ]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <bits/stdc++.h>
using namespace std;
typedef vector<int> vi;
int LowerBound(const vi& arr, int target) {
int low = 0, high = arr.size();
while (low < high) {
int mid = (low + high) / 2;
if (arr[mid] >= target) high = mid;
else low = mid + 1;
}
return low;
}
int UpperBound(const vi& arr, int target) {
int low = 0, high = arr.size();
while (low < high) {
int mid = (low + high) / 2;
if (arr[mid] > target) high = mid;
else low = mid + 1;
}
return low;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int cntCard; cin >> cntCard;
vi cards(cntCard);
for (int i = 0; i < cntCard; i++)
cin >> cards[i];
sort(cards.begin(), cards.end());
int cntNum; cin >> cntNum;
vi nums(cntNum);
for (int i = 0; i < cntNum; i++)
cin >> nums[i];
for (const auto& num : nums) {
int left = LowerBound(cards, num);
int right = UpperBound(cards, num);
cout << right - left << " ";
}
cout << "\n";
return 0;
}