这应该又是一道 HNOI 的普及 DP 吧。。。
可以发现,每次插入后都将是一个连续的区间,所以就是区间 DP 辣
设 \(f(i,j,0)\) 为区间 \([i,j]\) 最后一个推进 \(i\) 的方案数,\(f(i,j,1)\) 为最后一个推进 \(j\)。
\[ \begin{cases} f(i,j,0) = f(i + 1,j,0) + f(i + 1,j,1) & A_i < A_{i + 1}\;and\;A_i < A_j \\ f(i,j,1) = f(i,j - 1,1) + f(i,j - 1, 0) & A_r > A_{r - 1} \;and\;A_r > A_l \end{cases} \]
最终答案就是 \(f(1,n,0)+f(1,n,1)\)
边界条件只要将区间长度为 \(2\) 的情况特判下就行了。
#include <iostream>
#include <cstdio>
const int Mod = 19650827;
const int MaxN = 1000 + 5;
int N;
int A[MaxN], Dp[MaxN][MaxN][2];
inline int read()
{
register int x = 0;
register char ch = getchar();
while(!isdigit(ch)) ch = getchar();
while(isdigit(ch))
{
x = x * 10 + ch - '0';
ch = getchar();
}
return x;
}
int main()
{
N = read();
for(int i = 1; i <= N; ++i) A[i] = read();
for(int len = 2; len <= N; ++len)
{
for(int l = 1; l + len - 1 <= N; ++l)
{
int r = l + len - 1;
if(len == 2)
{
if(A[l] < A[r]) Dp[l][r][0] = Dp[l][r][1] = 1;
continue;
}
if(A[l] < A[l + 1]) Dp[l][r][0] += Dp[l + 1][r][0];
if(A[l] < A[r]) Dp[l][r][0] += Dp[l + 1][r][1];
Dp[l][r][0] %= Mod;
if(A[r] > A[r - 1]) Dp[l][r][1] += Dp[l][r - 1][1];
if(A[r] > A[l]) Dp[l][r][1] += Dp[l][r - 1][0];
Dp[l][r][1] %= Mod;
}
}
printf("%d\n", (Dp[1][N][0] + Dp[1][N][1]) % Mod);
return 0;
}