DP - [USACO16OPEN] - 262144P
DP - [USACO16OPEN] - 262144P
\(dp[i][j]\)表示从第i个数开始,向右合成数j,最后一个用到的数(右端点)的位置
假如我们想要从第\(i\)个数开始,合成数j,首先需要\(dp[i][j-1] \neq 0\),因为只有先合成\(j-1\)才能得到\(j\)。此外,还需要\(dp[dp[i][j-1]+1][j-1] \neq 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;
}
---- suffer now and live the rest of your life as a champion ----