首页 > 代码库 > uestc oj 1217 The Battle of Chibi (dp + 离散化 + 树状数组)
uestc oj 1217 The Battle of Chibi (dp + 离散化 + 树状数组)
题目链接:http://acm.uestc.edu.cn/#/problem/show/1217
给你一个长为n的数组,问你有多少个长度严格为m的上升子序列。
dp[i][j]表示以a[i]结尾长为j的上升子序列个数。常规是三个for。
这里用树状数组优化一下,类似前缀和的处理,两个for就好了。
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 long long LL;15 typedef pair <int, int> P;16 const int N = 1e3 + 5;17 LL dp[N][N], mod = 1e9 + 7;18 int a[N], b[N], m, n;19 LL bit[N][N];20 21 void add(int pos, int i, int val) { //上升子序列长度为pos 22 for( ; i <= n; i += (i&-i))23 bit[pos][i] = (bit[pos][i] + val) % mod;24 }25 26 LL sum(int pos, int i) {27 LL s = 0;28 for( ; i >= 1; i -= (i&-i))29 s = (s + bit[pos][i]) % mod;30 return s;31 }32 33 int main()34 {35 int t;36 scanf("%d", &t);37 for(int ca = 1; ca <= t; ++ca) {38 scanf("%d %d", &n, &m);39 for(int i = 1; i <= n; ++i) {40 scanf("%d", a + i);41 b[i] = a[i];42 }43 sort(b + 1, b + n + 1);44 for(int i = 1; i <= n; ++i) {45 a[i] = lower_bound(b + 1, b + n + 1, a[i]) - b; //离散化46 }47 memset(dp, 0, sizeof(dp));48 memset(bit, 0, sizeof(bit));49 dp[1][1] = 1;50 add(1, a[1], 1);51 for(int i = 2; i <= n; ++i) {52 dp[i][1] = 1;53 for(int k = max(m - (n - i), 1); k <= min(i, m); ++k) { //这边可以优化一下54 dp[i][k] = (dp[i][k] + sum(k - 1, a[i] - 1)) % mod; //比a[i]小且上升子序列长度为k-155 add(k, a[i], dp[i][k]);56 }57 }58 LL res = 0;59 for(int i = 1; i <= n; ++i) {60 res = (res + dp[i][m]) % mod;61 }62 printf("Case #%d: %lld\n", ca, res);63 }64 return 0; 65 }
uestc oj 1217 The Battle of Chibi (dp + 离散化 + 树状数组)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。