AGC029C - Lexicographic constraints 题解
Posted withhope
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AGC029C - Lexicographic constraints 题解相关的知识,希望对你有一定的参考价值。
原题链接:C - Lexicographic constraints
题目大意:有(N)个字符串,已知它们是从小到大排列的(按照字典序),现在仅知道每个字符串的长度,问这些字符串的字符集最小是多少。
题解:上来直接考虑贪心,似乎不大行,然后想DP,乱七八糟后效性一大堆,于是开始考虑二分答案。
首先特判掉1的情况(所有字符串长度严格递增),然后考虑二分答案(x),贪心思路很好想,就是在(x)进制下摆数,看能不能摆下。
字符串长度(leq 10^9),看上去要爆,但是,实际上的非零位置不会超过(n)个,只需要对这些非零位处理即可,时间复杂度(O(nlog n))。
代码:
#include <cstdio>
void read(int &a){
a=0;
char c=getchar();
while(c<'0'||c>'9'){
c=getchar();
}
while(c>='0'&&c<='9'){
a=(a<<1)+(a<<3)+(c^48);
c=getchar();
}
}
const int Maxn=200000;
int a[Maxn+5];
int n;
int pos[Maxn+5],num[Maxn+5],len;
bool check(int x){
len=0;
num[0]=0;
for(int i=1;i<=n;i++){
if(a[i]>a[i-1]){
continue;
}
if(len==0){
pos[++len]=a[i];
num[len]=1;
continue;
}
while(len>0&&pos[len]>a[i]){
len--;
}
if(len>0&&pos[len]==a[i]){
num[len]++;
while(len>0&&num[len]==x){
int now=pos[len]-1;
len--;
if(pos[len]==now){
num[len]++;
}
else{
pos[++len]=now;
num[len]=1;
}
}
}
else{
pos[++len]=a[i];
num[len]=1;
}
if(num[0]>0){
return 0;
}
}
return 1;
}
int main(){
read(n);
bool one=1;
for(int i=1;i<=n;i++){
read(a[i]);
if(a[i]<=a[i-1]){
one=0;
}
}
if(one){
puts("1");
return 0;
}
int left=2,right=n,mid;
while(left<right){
mid=(left+right)>>1;
if(check(mid)){
right=mid;
}
else{
left=mid+1;
}
}
printf("%d
",left);
return 0;
}
以上是关于AGC029C - Lexicographic constraints 题解的主要内容,如果未能解决你的问题,请参考以下文章
URAL1081 Binary Lexicographic Sequence(递归)