UVA12983题解

我们来看一下这道题:

  1. 离散,毕竟 $a_i$ 达到 $10^9$,而 $n$ 只达到 $10^3$

  2. 动态规划 :设 $dp_{i, j}$ 代表 $A$ 的前 $j$ 个数构成以 $a_j$ 为结尾,长度为 $i$ 的严格递增子序列有多少个,则

    $dp_{i, j}$ = $\sum\limits_{k = 1}^i(a_k < a_j) dp_{i - 1, k}$

  3. 树状数组优化:首先把外层循环 $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;
} 
posted @ 2021-06-05 16:37  wangzhongyuan  阅读(4)  评论(0编辑  收藏  举报  来源