这个题是bestcoder #8 的第三个。 比赛时用O(n*n)的dp做超时。 赛后看了hdu官网的题解, 用树状数组优化O(n*n*m)的dp。弱渣开眼了。。。
首先数字有1万个,先离散化一下,把所有数字对应到1到n之间。这样对结果不影响。 dp[i][j]代表以第i个数字结尾上升子序列长度为j的种数。 if(a[i]>a[k] && i>k) dp[i][j]=sum{dp[k][j-1]} 在练习赛的时候又碰到了,竟然一点印象也没有。所以重新做了一遍,之前写的代码也太乱了。#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> #include <vector> using namespace std; const int maxn=11000; const int MOD=123456789; int bit[110][maxn], arr[maxn], tmp[maxn]; int lowbit(int x) { return x&-x; } int Sum(int x, int i) { int res=0; for(; i>0; res=(res+bit[x][i])%MOD, i-=lowbit(i)); return res%MOD; } void Add(int x, int i, int v, int n) { for(; i<=n; bit[x][i]=(bit[x][i]+v)%MOD, i+=lowbit(i)); } int main() { // freopen("in.txt", "r", stdin); int n, len; while(~scanf("%d%d", &n, &len)) { for(int i=0; i<n; i++) { scanf("%d", arr+i); tmp[i]=arr[i]; } sort(tmp, tmp+n); int cnt=unique(tmp, tmp+n)-tmp; for(int i=0; i<n; i++) arr[i]=lower_bound(tmp, tmp+cnt, arr[i])-tmp+1; memset(bit, 0, sizeof(bit)); Add(1, arr[0], 1, cnt); for(int j=1; j<n; j++) { for(int i=2; i<=len; i++) { int t=Sum(i-1, arr[j]-1); Add(i, arr[j], t, cnt); } Add(1, arr[j], 1, cnt); } printf("%d\n", Sum(len, cnt)); } return 0; }