USACO16OPEN 262144

题目地址

题解

奇妙的做法。
考虑倍增,由于合并必然是一整段连续的序列,所以
设$f(i,j)$表示从$j$开始一直合并,直到出现$i$时的下标(开)。
然后就可以倍增了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cctype>
using namespace std;
typedef long long ll;
int f[65][270000]={0},n,ans=0;
void init(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
int u;
scanf("%d",&u),f[u][i]=i+1;//左闭右开
ans=max(ans,u);
}
}
void solve(){
for(int i=2;i<=60;i++){
for(int j=1;j<=n;j++){
if(!f[i][j]&&f[i-1][j]&&f[i-1][f[i-1][j]])
f[i][j]=f[i-1][f[i-1][j]],
ans=max(ans,i);
}
}
printf("%d\n",ans);
}
int main(){
init();
solve();
return 0;
}