Codeforces 597C. Subsequences (树状数组+dp)

题目链接:http://codeforces.com/contest/597/problem/C

给你n和数(1~n各不同),问你长为k+1的上升自序列有多少。

dp[i][j] 表示末尾数字为i 长度为j的上升子序列个数,但是dp数组是在树状数组的update函数中进行更新。

update(i, val, j)函数表示在i的位置加上val,更新dp[i][j]。

sum(i, j)就是求出末尾数字小于等于i 且长度为j的子序列有多少个。

 1 //#pragma comment(linker, "/STACK:102400000, 102400000")
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <cstdlib>
 5 #include <cstring>
 6 #include <cstdio>
 7 #include <vector>
 8 #include <cmath>
 9 #include <ctime>
10 #include <list>
11 #include <set>
12 #include <map>
13 using namespace std;
14 typedef __int64 LL;
15 typedef pair <int, int> P;
16 const int N = 1e5 + 5;
17 int a[N], n;
18 LL dp[N][15];
19 
20 void update(int i, LL val, int c) {
21     for( ; i <= n; i += (i&-i))
22         dp[i][c] += val;
23 }
24 
25 LL sum(int i, int c) {
26     LL s = 0;
27     for( ; i >= 1; i -= (i&-i))
28         s += dp[i][c];
29     return s;
30 }
31 
32 LL Cnm(LL a, LL b) {
33     if(b > a)
34         return 0;
35     LL res1 = 1, res2 = 1;
36     for(LL i = 0; i < b; ++i) {
37         res1 *= (a - i);
38         res2 *= (b - i);
39     }
40     return res1 / res2;
41 }
42 
43 int main()
44 {
45     int k;
46     scanf("%d %d", &n, &k);
47     k++;
48     LL res = 0;
49     for(int i = 1; i <= n; ++i) {
50         scanf("%d", a + i);
51         for(int j = 1; j <= k; ++j) {
52             if(j == 1) {
53                 update(a[i], 1, j);
54                 continue;
55             }
56             LL temp = sum(a[i] - 1, j - 1);
57             if(temp) {
58                 update(a[i], temp, j);
59             }
60         }
61     }
62     printf("%lld\n", sum(n, k));
63     return 0;
64 }

 

posted @ 2016-08-06 22:50  Recoder  阅读(85)  评论(0编辑  收藏