HDU 4990 Ordered Subsequence --数据结构优化DP
题意:给一串数字,问长度为m的严格上升子序列有多少个
解法:首先可以离散化为10000以内,再进行dp,令dp[i][j]为以第i个元素结尾的长度为j的上升子序列的个数,
则有dp[i][j] = SUM(dp[k][j-1]) (a[k] < a[i] && k < i)
不可能直接遍历,所以考虑优化,可以看出dp方程相当于一个区间求和,所以可以用树状数组来优化。
代码:
#include <iostream> #include <cmath> #include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <algorithm> #define SMod 123456789 #define lll __int64 using namespace std; #define N 10007 lll c[N],a[N],b[N]; int n,m; lll dp[N][104]; int lowbit(int x) { return x & (-x); } void modify(int pos,lll val) { while(pos <= n) { c[pos] += val; pos += lowbit(pos); } } lll getsum(int pos) { lll res = 0; while(pos > 0) { res = (res+c[pos])%SMod; pos -= lowbit(pos); } return res; } int main() { int i,j; while(scanf("%d%d",&n,&m)!=EOF) { for(i=1;i<=n;i++) { scanf("%I64d",&a[i]); b[i] = a[i]; } sort(b+1,b+n+1); memset(dp,0,sizeof(dp)); for(i=1;i<=n;i++) dp[i][1] = 1; for(j=2;j<=m;j++) { memset(c,0,sizeof(c)); for(i=1;i<=n;i++) { int ind = lower_bound(b+1,b+n+1,a[i])-b; dp[i][j] = getsum(ind-1); modify(ind,dp[i][j-1]); } } lll ans = 0; for(i=1;i<=n;i++) ans = (ans + dp[i][m])%SMod; printf("%I64d\n",ans); } return 0; }
作者:whatbeg
出处1:http://whatbeg.com/
出处2:http://www.cnblogs.com/whatbeg/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
更多精彩文章抢先看?详见我的独立博客: whatbeg.com