「AGC029C」Lexicographic constraints
「AGC029C」Lexicographic constraints
好像这个题非常 easy。
首先这个答案显然具有可二分性,所以问题转化为如何判定给定的 \(k\) 是否可行。
如果 \(a_k>a_{k-1}\),那么显然可以不用进位,直接在后面加一串最小字符即可。
否则需要进位,这个进位随便用个啥维护都行,因为进位次数是 \(O(n)\) 级别的。
但是我 \(\texttt{TLE}\) 了。。。
原因有两个:
- 注意到这个进位算法在 \(k=1\) 的时候会爆掉,所以你可能需要特判。
- 函数每次迭代如果返回一个值会慢很多,改成不需要返回值的版本即可。
这里提供一份用栈的代码:
/*---Author:HenryHuang---*/
/*---Never Settle---*/
#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5+5;
int a[maxn],n;
int fff=1;
stack<pair<int,int> > s;
void insert(int x,int lim){
if(x==0){
fff=1;
return ;
}
while(!s.empty()&&s.top().first>x) s.pop();
if(!s.empty()&&s.top().first==x){
++s.top().second;
}
else s.emplace(x,1);
if(!s.empty()&&s.top().second==lim){
s.pop();
insert(x-1,lim);
}
}
bool check(int xx){
while(!s.empty()) s.pop();
s.emplace(0,0);fff=0;
for(int i=1;i<=n;++i){
if(a[i]>a[i-1]){
continue;
}
insert(a[i],xx);
if(fff) return 0;
}
return 1;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n;
for(int i=1;i<=n;++i) cin>>a[i];
int flag=1;
for(int i=1;i<=n;++i) flag&=(a[i]>a[i-1]);
if(flag) cout<<1<<'\n',exit(0);
int l=2,r=n,ans=n;
while(l<=r){
int mid=(l+r)>>1;
if(check(mid)) ans=min(ans,mid),r=mid-1;
else l=mid+1;
}
cout<<ans<<'\n';
return 0;
}
在繁华中沉淀自我,在乱世中静静伫立,一笔一划,雕刻时光。