【AtCoder】ABC 443 C - Chokutter Addiction

C - Chokutter Addictionatcoder.jp favicon

実行時間制限: 2 sec / メモリ制限: 1024 MiB / Difficulty: 150 / NoviSteps: 3Q / 配点: 300 点

問題概要

AtCoder 社は時刻 00 に始業し時刻 TT に終業する。 ここで、時刻 tt と時刻 t+1t+1 との間隔は 11 秒である。

高橋君は AtCoder 社の業務時間中に SNS の chokutter を以下の規則で見る。

  • 始業と同時に chokutter を開く。
  • 青木君が高橋君のデスクの後ろを通りかかった瞬間に chokutter を開いていた場合、直ちに chokutter を閉じる。
  • 高橋君は、 chokutter を時刻 tt に閉じると、時刻 t+100t+100 に必ず chokutter を開く。

始業から終業までに NN 回青木君が高橋君のデスクの後ろを通りかかっており、そのうち ii 回目は時刻 AiA_i であった。 始業から終業までに、高橋君は合計で何秒 chokutter を見ていたか求めよ。

制約

  • 入力は全て整数
  • 0N3×1050 \le N \le 3 \times 10^5
  • 1A1<A2<<ANT1091 \le A_1 < A_2 < \dots < A_N \le T \le 10^9
  • 高橋君が chokutter を開いた瞬間に青木君がデスクの後ろを通りかかることはない

考察

この問題は愚直にシミュレーションを行うことで解くことができる。

具体的には、高橋君が chokutter を見ていた総時間 total\mathrm{total} 、最後に開いた時刻 ll, 現在 chokutter を開いているかどうかのフラグ ff を管理しながら、


  • 初期状態 : total=0,l=0,f=true\mathrm{total} = 0, l = 0, f = \mathrm{true} とする。
  • 青木君がやってくるごとに(各 i=1,2,,Ni = 1, 2, \ldots, N について)、次の処理を行う。
    • f=truef = \mathrm{true} である場合、ここまでの閲覧時間を記録する。
      • totaltotal+(Ail)\mathrm{total} \leftarrow \mathrm{total} + (A_i - l) とし、 ffalsef \leftarrow \mathrm{false} とする。
    • 次に chokutter を開く時刻を t=Ai+100t^{\prime} = A_i + 100 とする。
    • t<Tt^{\prime} < T である(終業時刻までにもう一度開くことができる)場合、
      • Ai<tA_i < t^{\prime} である間 ii をインクリメントし、閉じている間に青木君がやってきてもスキップする。
      • その後、lt,ftruel \leftarrow t^{\prime}, \quad f \leftarrow \mathrm{true} として、chokutter を再度開く。
    • そうでない場合、 lTl \leftarrow T とし、 ffalsef \leftarrow \mathrm{false} とする。
  • 最後に、 f=truef = \mathrm{true} である場合、終業時刻まで閲覧していた時間を記録する。
    • totaltotal+(Tl)\mathrm{total} \leftarrow \mathrm{total} + (T - l) とする。

のようにシミュレーションを行えばよい。実装例も参照のこと。

実装例

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.// ======================================== //
7.
8.int main()
9.{
10. int N, T;
11. cin >> N >> T;
12. vector<int> A(N);
13. rep(i, 0, N) cin >> A[i];
14.
15. int ans = 0, last_open_time = 0;
16. bool is_open = true;
17. rep(i, 0, N)
18. {
19. if (is_open)
20. {
21. ans += A[i] - last_open_time;
22. is_open = false;
23. }
24.
25. int next_open_time = A[i] + 100;
26.
27. if (next_open_time < T)
28. {
29. while (i + 1 < N && A[i + 1] < next_open_time)
30. {
31. i++;
32. }
33.
34. last_open_time = next_open_time;
35. is_open = true;
36. }
37. else
38. {
39. last_open_time = T;
40. is_open = false;
41. }
42. }
43.
44. if (is_open && last_open_time < T)
45. {
46. ans += T - last_open_time;
47. }
48.
49. cout << ans << endl;
50. return 0;
51.}
Submission #72878222 - Denso Create Programming Contest 2026(AtCoder Beginner Contest 443)atcoder.jp favicon

実装時間: 5 分

コメント

C問題にしては素直なシミュレーション問題だった。