2015 CCPC
- 求问长度为m的上升子序列的个数,m<=n<=1000.
- dp[i][j]表示包含第i个数的长度为j的上升子序列个数,那么显然是从前i-1个数
- 中小于等于a[i]的长度为j-1的状态求和转移过来,离散化后就用树状数组维护这个
- 转移就好了。
#include <map>#include <cstdio>#include <utility>#include <cstring>#include <iostream>#include <algorithm>const int maxn = 1007;const int mo = 1e9+7;int n, m;int a[maxn], b[maxn];long long bit[maxn][maxn];void add(int j, int k, long long add){ for(k; k <= n; k += -k & k){ bit[j][k] = (bit[j][k] + add) % mo; }}long long sum(int j, int k){ long long ret = 0ll; for(; k; k -= - k & k){ ret = (ret + bit[j][k]) % mo; } return ret;}int main(){ int T; scanf("%d", &T); for(int ti = 1; ti <= T; ti ++){ std::map<int, int> map; memset(bit, 0, sizeof(bit)); scanf("%d %d", &n, &m); for(int i = 1; i <= n; i ++){ scanf("%d", &a[i]); b[i] = a[i]; } int count = 0; std::sort(b+1, b+n+1); for(int i = 1; i <= n; i ++){ if(b[i] > b[i - 1]) map[b[i]] = ++count; else map[b[i]] = count; } for(int i = 1; i <= n; i ++){ add(1, map[a[i]], 1); for(int j = 2; j <= m; j ++){ long long temp = sum(j - 1, map[a[i]] - 1) % mo; add(j, map[a[i]], temp);