DP - [USACO16OPEN] - 262144P
(dp[i][j])表示从第i个数开始,向右合成数j,最后一个用到的数(右端点)的位置
假如我们想要从第(i)个数开始,合成数j,首先需要(dp[i][j-1] eq 0),因为只有先合成(j-1)才能得到(j)。此外,还需要(dp[dp[i][j-1]+1][j-1] eq 0),这是因为,除了这一段合成(j-1),还需要下一段合成(j-1),才能将两个(j-1)合成一个(j)。因此,可知dp过程:
// init
for(int i = 1; i <= n; ++i)
cin >> a[i];
// init dp
for(int i = 1; i <= n; ++i)
dp[i][a[i]] = i;
// dp
for(int i = n; i >= 1; --i){
for(int j = a[i]+1; j <= 60; ++j){
if(dp[i][j])
}
}
完整代码
#include <bits/stdc++.h>
using namespace std;
const int N = 262144+5;
int n;
int a[N];
int dp[N][80]; // 从第i个数开始, 向右边合成数j,得到的右端点为x
int main(){
cin >> n;
for(int i = 1; i <= n; ++i)
cin >> a[i];
for(int i = 1; i <= n; ++i){
dp[i][a[i]] = i;
}
for(int i = n-1; i >= 1; --i){
for(int j = a[i]+1; j <= 60; ++j){
if(dp[i][j-1] && dp[i][j-1]+1 <= n && dp[dp[i][j-1]+1][j-1])
dp[i][j] = dp[dp[i][j-1]+1][j-1];
}
}
int ans = 0;
for(int j = 1; j <= 60; ++j){
for(int i = 1; i <= n; ++i){
if(dp[i][j]){
ans = max(ans, j);
break;
}
}
}
cout << ans << endl;
return 0;
}