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 }