题目链接
题目大意
给定一串序列,问有多少种初始序列经过以下操作可以得到此序列:
① 、第一个数直接插入空的当前序列中
② 、对从第二个数开始的每个数,如果它比上一个插入序列的数大,那么将它插入当前序列的最右边
如果它比上一个插入序列的数小,那么将它插入当前序列的最左边
解题思路
定义 (dp1[i][j]) 的含义为构成理想区间([i , j]) ,最后一个被放入的是 (i) 的方案数
定义 (dp2[i][j]) 的含义为构成理想区间([i , j]) ,最后一个被放入的是 (j) 的方案数
一、
对于 (dp1)
区间 ([i , j]) 的上一个区间为 ([i + 1 , j])
而构成区间 ([i + 1][j]) 的序列的末尾可能是 (a[i + 1]) ,也可能是 (a[j])
所以:
①.当 (a[i] < a[i + 1]) 时 , (dp1[i][j] += dp1[i + 1][j])
②.当 (a[i] < a[j]) 时 , (dp1[i][j] += dp2[i + 1][j])
二、
对于 (dp2)
区间 ([i , j]) 的上一个区间为 ([i , j - 1])
而构成区间 ([i][j - 1]) 的序列的末尾可能是 (a[i]) ,也可能是 (a[j - 1])
①.当 (a[j] > a[i]) 时 , (dp2[i][j] += dp1[i][j - 1])
②.当 (a[j] > a[j - 1]) 时 , (dp2[i][j] += dp2[i][j - 1])
最后 $ans = dp1[1][n] + dp2[1][n] $
注意:当 (i = j) 即区间长度为 (1) 时 , 只需让 (dp1 = 1) or (dp2 = 1) 即可
即构造区间长度为 (1) 的方案数只有 (1)
若让 (dp1) 和 (dp2) 都等于 (1) 则相当于构造区间长度为 (1) 的方案数为 (1 + 1 = 2 (×))
AC_Code
#include<bits/stdc++.h>
using namespace std;
const int N = 2e3 + 10 , mod = 19650827;
int n , a[N];
int dp1[N][N] , dp2[N][N];
signed main()
{
cin >> n;
for(int i = 1 ; i <= n ; i ++) cin >> a[i] , dp1[i][i] = 1;
for(int len = 1 ; len <= n ; len ++)
{
for(int i = 1 ; i + len <= n ; i ++)
{
int j = i + len;
{
if(a[i] < a[i + 1]) dp1[i][j] += dp1[i + 1][j];
if(a[i] < a[j]) dp1[i][j] += dp2[i + 1][j];
if(a[j] > a[i]) dp2[i][j] += dp1[i][j - 1];
if(a[j] > a[j - 1]) dp2[i][j] += dp2[i][j - 1];
dp1[i][j] %= mod , dp2[i][j] %= mod;
}
}
}
cout << (dp1[1][n] + dp2[1][n]) % mod << '
';
return 0;
}