[AGC029] C - Lexicographic constraints

[Q] https://atcoder.jp/contests/agc029/tasks/agc029_c

考察
1. 使用する種類数で二分探索する。
2. 種類数が十分かどうか、のシミュレートはどのくらい?
3. N要素をひと舐めする必要がある。mapでO(NlogN)でいけそう。
4. mapでどう管理しよう
(1). 値が減る場合の処理
->末尾を+1する。
->末尾を+1できない場合は桁上げする。
->桁上げが尽きたらfalse
(2). 値が増える場合の処理
->新しい末尾に0を追加する

入力例2
N=5
A:2 3 2 1 2

1. 種類数は 1 ~ 5 まであるので、にぶたん
2. mid = 2 としてシミュレートする

・A[0] = 2
M[2] = 0 (aa)

・A[1] = 3
M[2] = 0
M[3] = 0 (aaa)

・A[2] = 2
M[2] = 1 (ab)

M[2]以降にある要素は全部削除する。
M[2]を1加算する。

・A[3] = 1
M[1] = 1 (b)
M[1]以降にある要素を全部削除する。
M[1]=0を仮置きしたあと、M[1]を1加算する。

・A[4] = 2
M[1] = 1
M[2] = 0 (ba)
末尾に追加するだけなので、M[2] = 0を追加。

これが最短なので2が回答。

Q. もしA[]が昇順だったら?
A. a->aa->aaa...とすればいいので、1種類でいける。

実装

ll A[200020];
ll N;

ll binary_search(ll R) {
 ll L = 0;
 while (R - L > 1) {
   ll mid = (L + R) / 2;
   map<ll, ll> M;
   bool ok = true;
   rep(i, N) {
     ll a = A[i];
     bool is_first = false;
     if (M.count(a) == 0) is_first = true;
     M[a]; // ないならM[a]=0を生成
     auto it = M.find(a);
     auto nit = it;
     ++nit;
     // つけたしたのが末端なら、そこでおしまい。
     if (nit == M.end() && is_first) {
       continue;
     }
     // 以降を全部0にしておく
     while (nit != M.end()) {
       M.erase(nit++);
     }
     // 繰り下げする場合
     if (it->second == mid) {
       while (it->second == mid) {
         if (it->first == 0) break;
         M[it->first - 1];  // 1個前の桁がないなら0入れ
         M.erase(it--);
       }
       if (it->second == mid) { // false
         ok = false;
         break;
       }
       ++it->second;
     } else {
       ++it->second;
       ++it;
       while (it != M.end()) {
         M.erase(it++);
       }
     }
   }
   if (ok)
     R = mid;
   else
     L = mid;
 }
 return R;
}

int main() {
 cincout();

 cin >> N;
 rep(i, N) {
   cin >> A[i];
   --A[i];
 }
 ll p = -1;
 bool is_zero = true;
 rep(i, N) {
   if (p >= A[i]) {
     is_zero = false;
     break;
   }
   p = A[i];
 }
 if (is_zero) {
   cout << 1 << endl;
   return 0;
 }
 cout << binary_search(N) + 1 << endl;
}

https://atcoder.jp/contests/agc029/submissions/30578166

いいなと思ったら応援しよう!