配点: 350 点 / 実行時間制限: 2 sec / メモリ制限: 1024 MB / Difficulty: 378 / NoviSteps: ???
問題概要
長さ の文字列
が与えられる。
は
A, Bを 個ずつ含む。
に対して隣り合う文字を入れ替える操作を0回以上行って、同じ文字が隣り合う箇所がない状態にするために必要な操作回数の最小値を求めよ。
制約
は整数
考察
重要な考察として、最終的な文字列の状態 には
ABAB ... ABとBABA ... BAの2パターンしかない。
また、 における
Aの順序と における
Aの順序を入れ替えるような操作はする必要がない。
したがって、 における先頭から
番目の
Aを、 における先頭から
番目の
Aに移すための操作回数を最小化すればよい。
この回数は、 を
における先頭から
番目の
Aのインデックスを格納した配列とすれば、例えば ABAB ... ABなら、Aは の偶数番目に配置したいので、
であり、BABA ... BAなら、Aは の奇数番目に配置したいので、
と計算できる。
あとは両者の小さい方を答えとすればよい。
実装例
#include <bits/stdc++.h> using namespace std; #define rep(i, start, end) for (auto i = (start); (i) < (end); (i)++) using ll = long long; // ======================================== // int main() { int N; string S; cin >> N >> S; vector<int> pos_A; rep(i, 0, 2 * N) { if (S[i] == 'A') pos_A.push_back(i); } ll cost1 = 0, cost2 = 0; rep(i, 0, N) { cost1 += abs(pos_A[i] - (2 * i)); cost2 += abs(pos_A[i] - (2 * i + 1)); } cout << min(cost1, cost2) << endl; return 0; }
実装時間: 20分
コメント
一番最初の考察が思いつくかどうか。なんとなく「kyopro_friends さんが作るC問題っぽいなー」という気がする。