AGC029 C - Lexicographic constraints

ICPCっぽさを感じるね。

考察

二部探索をする、「K種類の文字で実現可能か」について考える。

愚直にやろうとすると10^9桁考えなくてはいけなくなるのでRun Lengthといわれる(であろう)実装をする。

aaabbbabbccbbbb

a3b3a1b2c2b4

とかく奴です。
実際'a'は最下位のとき以外省略するみたいな書き方をしています。

コード

#include <bits/stdc++.h>

using namespace std;

#define REP(i,n) for(ll (i) = (0);(i) < (n);++i)
#define REV(i,n) for(ll (i) = (n) - 1;(i) >= 0;--i)
#define PB push_back
#define EB emplace_back
#define MP make_pair
#define FI first
#define SE second
#define SHOW1d(v,n) {REP(WW,n)cerr << v[WW] << ' ';cerr << endl << endl;}
#define SHOW2d(v,WW,HH) {REP(W_,WW){REP(H_,HH)cerr << v[W_][H_] << ' ';cerr << endl;}cerr << endl;}
#define ALL(v) v.begin(),v.end()
#define Decimal fixed<<setprecision(20)
#define INF 1000000000
#define LLINF 1000000000000000000LL
#define MOD 1000000007

typedef long long ll;
typedef pair<ll,ll> P;

bool naoppy(vector<ll> &v, ll mid) {
	vector<P> now;
	now.EB(0,-1);
	REP(i,v.size()){
		if(now.back().FI < v[i]){
			now.EB(v[i],0);
		}
		else {
			if(mid <= 1)return false;
			while(now.back().FI > v[i])now.pop_back();
			if(now.back().FI < v[i])now.EB(v[i],0);
			int tmp = now.back().FI;
			int top = now.back().FI;
			while(now.back().FI == top && now.back().SE == mid - 1){
				top = now.back().FI - 1;
				now.pop_back();
			}
			if(now.back().FI != top)now.EB(top,0);
			now.back().SE++;
			if(now.back().FI != tmp)now.EB(tmp,0);
			if(now.front().SE > -1)return false;
		}
		//REP(i,now.size())cout << "(" << now[i].FI << "," << now[i].SE << ") ";cout << endl;
	}
	return true;
}

int main(){
	
	ll n;cin >> n;
	vector<ll> v(n);
	REP(i,n)cin >> v[i];
	
	ll l = 0;
	ll r = 222222;
	
	while(r - l > 1){
		ll mid = (l + r) / 2;
		if(naoppy(v,mid))r = mid;
		else l = mid;
	}
	
	cout << r << endl;
	
	return 0;
}

上のコードについて、入力が

10
2 2 3 3 3 2 2 2 1 2

で、K = 3の時を見てみると、コメントされたところは

(0,-1) (2,0)
(0,-1) (2,1)
(0,-1) (2,1) (3,0)
(0,-1) (2,1) (3,1)
(0,-1) (2,1) (3,2)
(0,-1) (2,2)
(0,-1) (1,1) (2,0)
(0,-1) (1,1) (2,1)
(0,-1) (1,2)
(0,-1) (1,2) (2,0)

と出力される。(a, b)はa番目の文字がbというもの、書いていない桁はb=0です。
文字に置き換えると

aa
ab
aba
abb
abc
ac
ba
bb
c
ca

という感じでK=3で達成可能とわかる。
この実装では0桁目が-1でなくなったら失敗となります。

おまけ

私は意地が悪いので変数名にはしません。