UVA12983题解
我们来看一下这道题:
-
离散,毕竟 $a_i$ 达到 $10^9$,而 $n$ 只达到 $10^3$
-
动态规划 :设 $dp_{i, j}$ 代表 $A$ 的前 $j$ 个数构成以 $a_j$ 为结尾,长度为 $i$ 的严格递增子序列有多少个,则
$dp_{i, j}$ = $\sum\limits_{k = 1}^i(a_k < a_j) dp_{i - 1, k}$
-
树状数组优化:首先把外层循环 $i$ 看成一个定值,当 $j$ 增加一时,$k$ 的范围从 $1 \le k \le j - 1$ 到 $1 \le k \le j$,也就是说只多了 $k = j$ 的情况,可用树状数组优化
具体请看代码
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1010, mod = 1e9 + 7;
int n, m, cnt, a[maxn], b[maxn], t[maxn], dp[maxn][maxn];
int lowbit (int x) {
return x & (-x);
}
void add (int x, int p) {
for (; x <= n + 1; x += lowbit (x)) t[x] = (t[x] + p) % mod;
}
int query (int x) {
int sum = 0;
for (; x > 0; x -= lowbit (x)) sum = (sum + t[x]) % mod;
return sum;
}
int main() {
int T; scanf ("%d", &T);
while (T --) {
scanf ("%d%d", &n, &m);
for (int i = 1; i <= n; ++i) {
scanf ("%d", &a[i]); b[i] = a[i];
}
sort (b + 1, b + n + 1);
for (int i = 1; i <= n; ++i) a[i] = lower_bound (b + 1, b + n + 1, a[i]) - b + 1; // 离散化
a[0] = dp[0][0] = 1;
for (int i = 1; i <= m; ++i) {
memset (t, 0, sizeof (t));
add (1, dp[i - 1][0]);
for (int j = 1; j <= n; ++j) {
dp[i][j] = query (a[j] - 1);
add (a[j], dp[i - 1][j]);
}
} // 树状数组优化dp
int ans = 0;
for (int i = 1; i <= n; ++i) ans = (ans + dp[m][i]) % mod;
printf ("Case #%d: %d\n", ++cnt, ans); // 输出注意
}
return 0;
}