問題の意味
与えられた\(N- \)文字列の長さ\(a_iを\) 、辞書式順序の比較構築するために使用される文字の最小数を見つける\(S1 <S2 <⋯<Snの\を)。
\(1 \当量N \の当量 2 \回10 ^ 5,1 \当量a_iを\当量10 ^ 9 \)
考え
場合は、進数として文字列を見ることができます\(A_ {I + 1} > a_iをを\) に直接補完(0 \)\をすれば、そうでない場合は、彼が第一の長さを見つけるよりも、もう少しのために、作るのに十分な長ません\(0 \) 、その後、\(+ 1 \) 、最後のバースト仮数になります。\(1 \)文字は、特殊な文アウトすることができ、実際には、それは残りの中に見つけることができます\(マップ\)メンテナンス
もちろん、答えに二つの点が二分法があります。
#include <bits/stdc++.h>
using namespace std;
const int N=200005;
int n,a[N],ans,f=0;
map <int,int> mp;
bool check(int x){
mp.clear();
for (int i=2;i<=n;i++)
if (a[i-1]>=a[i]){
while (!mp.empty()){
int t=mp.rbegin()->first;
if (t>a[i]) mp.erase(t);
else break;
}
int j=a[i];
while (mp[j]+1==x) mp.erase(j),j--;
if (j==0) return false;
mp[j]++;
}
return true;
}
int main(){
scanf("%d",&n);
for (int i=1;i<=n;i++) {
scanf("%d",&a[i]);
if (a[i]<=a[i-1]) f=1;
}
if (!f) {puts("1");return 0;}
int l=2,r=n;
while (l<=r){
int mid=(l+r)>>1;
if (check(mid)){
ans=mid;
r=mid-1;
}else l=mid+1;
}
printf("%d\n",ans);
}