Problem: https://atcoder.jp/contests/abc430/tasks/abc430_c
C - Truck Driver
AtCoder is a programming contest site for anyone from beginners to experts. We hold weekly programming contests online.
atcoder.jp
문제 요약
'a' 와 'b'로만 이루어진 문자열S가 주어진다. (e.g. abbaaabaaba)
문자열 S에서, 'a'가 A개 이상이고, 'b'가 B미만인 부분 문자열의 갯수를 구하여라.
예시1)
| S | abbaaabaaba |
| A | 4 |
| B | 2 |
정답: 3
부문 문자열1 (4, 8): aaaba
부분 문자열2 (4, 9): aaabaa
부분 문자열3 (5, 9): aabaa
예시2)
| S | bbbbbbbbbbbbb |
| A | 1 |
| B | 2 |
정답: 0
조건에 맞는 부분 문자열 없음
문제 풀이
문제에서 몇 가지 사실을 간파해야한다.
① 문자 'a'와 'b'의 갯수는 index가 뒤로 갈수록, 갯수가 늘어난다.
이것은 prefix sum을 사용하여 특정 인덱스에서 'a'나 'b'가 등장한 횟수를 효율적으로 계산할 수 있음을 의미한다.
② prefix sum은 정렬되어 있으므로, 이진탐색으로 조건에 맞는 index를 빠르게 찾을 수 있다.
prefix sum에서 구하고 싶은 것(index)은 무엇일까?
prefix sum(a): 'a'가 언제부터 A번 이상 등장하는가? → 해당 인덱스 이후로는 'a'는 항상 A번 이상이다
prefix sum(b): 'b'가 언제까지 B번 미만 등장했는가? → 해당 인덱스까지만 'b'는 B번 미만 등장한 것이다.
③ 조건에 맞는 부분 문자열을 찾아야 한다. → 탐색 범위를 제한해야 한다.

④ prefix sum에서 탐색 범위를 제한하는 것은, 단순히 범위만 제한한다고 되는 것이 아니다.
제한되는 범위에 맞춰서, 찾고자 하는 값(target)도 변해야 올바른 탐색을 할 수 있다.

⑤ prefix_sum(a) 와 prefix_sum(b)에서 찾은 인덱스의 공통분모(유효구간)가 문제에서 찾는 답이다.

풀이 코드
#include <iostream>
#include <string>
#include <vector>
#include <iomanip>
using namespace std;
int main()
{
int N, A, B;
string S;
cin >> N >> A >> B >> S;
// prefix sum
vector<int> ps_a(N + 1, 0);
vector<int> ps_b(N + 1, 0);
for (int i = 0; i < N; i++)
{
ps_a[i + 1] = ps_a[i] + (S[i] == 'a');
ps_b[i + 1] = ps_b[i] + (S[i] == 'b');
}
long long answer = 0;
for (int i = 0; i < N; i++)
{
// i를 이용해 탐색 범위를 줄여나간다
// 찾는 target도 탐색 범위에 맞춰 변경해야 한다
auto it = lower_bound(ps_a.begin() + i, ps_a.end(), ps_a[i] + A);
int r_a = distance(ps_a.begin(), it);
it = lower_bound(ps_b.begin() + i, ps_b.end(), ps_b[i] + B);
int r_b = distance(ps_b.begin(), it) - 1;
if (r_a <= r_b) // 정답 수 세기
{
answer += r_b - r_a + 1;
}
}
cout << answer << "\n";
return 0;
}'Algorithm Problem > AtCoder' 카테고리의 다른 글
| Candy Tribulation (0) | 2025.11.17 |
|---|---|
| Security 2 (0) | 2025.05.25 |