Olympic Sinh Viên 2020 - Chuyên tin - VCA === [URL](https://oj.vnoi.info/problem/olp_ct20_vca) ----- ### Hướng dẫn Với mỗi vị trí $[L]$ tìm vị trí $[R]$ nhỏ nhất thỏa mãn số lượng kí tự '**A**', '**V**' và '**C**' trong đoạn $[L, R]$ đều không ít hơn $k$ Vì lúc này $[L, R]$ là một đoạn cố định tương tự như mình xóa $[1, L)$ và $(R, N]$ mà không mất chi phí, nên giờ mình sẽ xóa phần bên trong, sao cho số lượng '**A**', '**V**' và '**C**' đều có đúng $k$. Gọi $C(L, R, X)$ là số lượng kí tự có giá trị $X$ trên đoạn $[L, R]$. Chi phí sửa đổi của đoạn $[L, R]$ là $(C(L, R,$ '**A**' $) + C(L, R,$ '**C**'$) + C(L, R,$ '**V**'$) - 3k)$. Vậy bài này có độ phức tạp là $O(n)$ thời gian và bộ nhớ - Mình có thể tìm $R$ bằng hai con trỏ thay cho chặt nhị phân - Mình có thể sử dụng mảng cộng dồn hoặc một số cấu trúc dữ liệu để $O(n)$ tiền xử lí và $O(1)$ truy vấn. ----- ### Code > **Time:** $O(n)$ > **Space:** $O(n)$ > **Algo:** Two Pointers ```cpp= #inlude <iostream> using namespace std; int cnt[256]; int main() { /// Input int k; string s; cin >> k >> s; /// Calculate int res = +INF; cnt['A'] = cnt['V'] = cnt['C'] = 0; for (int l = 0, r = -1; l < s.size(); --cnt[s[l++]]) { while (r + 1 < s.size() && (cnt['A'] < k || cnt['V'] < k || cnt['C'] < k)) ++cnt[s[++r]]; if (cnt['A'] < k || cnt['V'] < k || cnt['C'] < k) break; int t = 0; t += cnt['A'] - k; t += cnt['V'] - k; t += cnt['C'] - k; minimize(res, t); } /// Output cout << res; return 0; } ```