【AtCoder】ABC 430 C - Truck Driver
AtCoder/ABC/C問題AtCoder/ABC/300点問題AtCoder/茶DiffAtCoder/NoviSteps/2QAtCoder/数え上げ/区間の個数AtCoder/累積和AtCoder/二分探索/lower_bound競技プログラミング

C - Truck Driver
AtCoder is a programming contest site for anyone from beginners to experts. We hold weekly programming contests online.
AtCoder
実行時間制限: 2 sec / メモリ制限: 1024 MiB / Difficulty: 750 / NoviSteps: 2Q / 配点: 300 点
問題概要
a, bからなる長さ の文字列 と正整数 が与えられる。
以下の条件を全て満たす整数組 の個数を求めよ。
- の 文字目から 文字目までに含まれる
aの個数が 以上 - の 文字目から 文字目までに含まれる
bの個数が 未満
制約
- 与えられる数値は全て整数
考察
を固定して、条件を満たす の個数を数え上げる典型問題である。
このときに、任意の区間内のaとbの個数を何度も計算する必要があるので、累積和を用いて高速に求められるようにしておく。
- の先頭から 文字目までに含まれる
aの個数 - の先頭から 文字目までに含まれる
bの個数
とすれば、 の 文字目から 文字目までに含まれるaの個数は 、bの個数は として、計算量 で求めることができる。
ここで をある値に固定したとき、 が満たすべき条件は以下のようになる。
累積和テーブルは単調増加なので、上記の条件を満たす はそれぞれ二分探索で求めることができる。
であれば、この に対して条件を満たす の個数は 個となるので、これを全ての について合計すればよい。
全体の計算量は である。
実装例
イテレータとインデックスの変換、そして の求め方に注意すること。
CPP
1.#include <bits/stdc++.h>2.using namespace std;3. 4.#define rep(i, start, end) for (auto i = (start); (i) < (end); (i)++)5. 6.using ll = long long;7. 8.// ======================================== //9. 10.int main()11.{12. int N, A, B;13. string S;14. cin >> N >> A >> B >> S;15. 16. vector<int> ps_a(N + 1, 0), ps_b(N + 1, 0);17. rep(i, 0, N)18. {19. if (S[i] == 'a')20. ps_a[i + 1] = ps_a[i] + 1;21. else22. ps_a[i + 1] = ps_a[i];23. 24. if (S[i] == 'b')25. ps_b[i + 1] = ps_b[i] + 1;26. else27. ps_b[i + 1] = ps_b[i];28. }29. 30. ll ans = 0;31. rep(l, 0, N)32. {33. auto itr_a = lower_bound(ps_a.begin() + (l + 1), ps_a.end(), ps_a[l] + A);34. auto itr_b = lower_bound(ps_b.begin() + (l + 1), ps_b.end(), ps_b[l] + B);35. 36. int r_a = distance(ps_a.begin(), itr_a) - 1;37. int r_b = (distance(ps_b.begin(), itr_b) - 1) - 1;38. 39. if (r_a <= r_b)40. ans += r_b - r_a + 1;41. }42. 43. cout << ans << endl;44. 45. return 0;46.}
Submission #70603378 - AtCoder Beginner Contest 430
AtCoder is a programming contest site for anyone from beginners to experts. We hold weekly programming contests online.
AtCoder
実装時間: 10 分
コメント
尺取り法でも解けるようだが、累積和 + 二分探索の方が個人的には実装しやすかった。





