题面
和通常套路不太一样,这题 (N le 262144),不可以通过枚举区间的方程转移出来。
实际上,我们通过合并最大可以得出 (58),这个 (58) 实际就是 (18 + 40),(40) 是显然的,但是 (18) 呢?
我们考虑合并的过程,实际与倍增过程类似,最多我们会合并 (log n) 次,再看看数据范围:(2^{18} = 262144)!
于是我们就有了代码中的方程。
代码:
# include <iostream>
# include <cstdio>
# define MAXN 60
# define MAXM 270000
int f[MAXM][MAXN]; // f[i][j] 以 i 为左端点,合并出 j 的答案
int a[MAXM];
int main(){
int n, ans = 0;
scanf("%d", &n);
for(int i = 1; i <= n; i++){
scanf("%d", &a[i]);
f[i][a[i]] = i+1;
}
for(int j = 2; j <= 58; j++){
for(int i = 1; i <= n; i++){
if(!f[i][j]){
f[i][j] = f[f[i][j-1]][j-1];
}
if(f[i][j]){
ans = std::max(ans, j);
}
}
}
printf("%d", ans);
return 0;
}