「AGC029C」Lexicographic constraints

「AGC029C」Lexicographic constraints

传送门

好像这个题非常 easy。

首先这个答案显然具有可二分性,所以问题转化为如何判定给定的 (k) 是否可行。

如果 (a_k>a_{k-1}),那么显然可以不用进位,直接在后面加一串最小字符即可。

否则需要进位,这个进位随便用个啥维护都行,因为进位次数是 (O(n)) 级别的。

但是我 ( exttt{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<<'
',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<<'
';
	return 0;
}
在繁华中沉淀自我,在乱世中静静伫立,一笔一划,雕刻时光。
原文地址:https://www.cnblogs.com/HenryHuang-Never-Settle/p/solution-AGC029C.html