hdu 3450(树状数组优化dp)
2016-06-14 15:21
369 查看
Counting Sequences
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/65536 K (Java/Others)[align=left]Problem Description[/align]
For a set of sequences of integers{a1,a2,a3,...an}, we define a sequence{ai1,ai2,ai3...aik}in which 1<=i1<i2<i3<...<ik<=n, as the sub-sequence of {a1,a2,a3,...an}. It is quite obvious that a sequence with the length n has 2^n sub-sequences.
And for a sub-sequence{ai1,ai2,ai3...aik},if it matches the following qualities: k >= 2, and the neighboring 2 elements have the difference not larger than d, it will be defined as a Perfect Sub-sequence. Now given an integer sequence, calculate the number
of its perfect sub-sequence.
[align=left]Input[/align]
Multiple test cases The first line will contain 2 integers n, d(2<=n<=100000,1<=d=<=10000000) The second line n integers, representing the suquence
[align=left]Output[/align]
The number of Perfect Sub-sequences mod 9901
[align=left]Sample Input[/align]
4 2
1 3 7 5
[align=left]Sample Output[/align]
4
解题思路:dp[i]表示前i个数的有效序列的个数,则dp[i] = sum{dp[k]},其中abs(a[k] - a[i]) <= d;时间复杂度为O(n²),需要优化。这里用树状数组优化,不过需要找到符合要求的区间段,对于一个数a[i],需要找的区间范围肯定是[a[i]-d,a[i]+d],这样就可以用二分把区间的位置找到了。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn = 100005; const int mod = 9901; struct Node { int value; int id; }num[maxn]; int n,d,cnt[maxn],dp[maxn]; int tree[maxn<<1]; bool cmp(Node a,Node b) { return a.value < b.value; } int lowbit(int x) { return x & -x; } void add(int x,int c) { for(int i = x; i <= n; i += lowbit(i)) tree[i] = (tree[i] + c) % mod; } int getsum(int x) { int ans = 0; for(int i = x; i > 0; i -= lowbit(i)) ans = (ans + tree[i]) % mod; return ans; } int find(int k) { int left = 1, right = n, ret = 0; while (left <= right) { int mid = (left + right) / 2; if (num[mid].value <= k) { ret = mid; left = mid + 1; } else right = mid - 1; } return ret; } int main() { while(scanf("%d%d",&n,&d)!=EOF) { for(int i = 1; i <= n; i++) { scanf("%d",&num[i].value); num[i].id = i; } sort(num+1,num+1+n,cmp); for(int i = 1; i <= n; i++) cnt[num[i].id] = i; memset(tree,0,sizeof(tree)); add(cnt[1],1); int ans = 0; for(int i = 2; i <= n; i++) { int k1 = find(num[cnt[i]].value + d); int k2 = find(num[cnt[i]].value - d - 1); int tmp = getsum(k1) - getsum(k2); tmp = (tmp % mod + mod) % mod; ans = (ans + tmp) % mod; add(cnt[i],tmp+1); } printf("%d\n",ans); } return 0; }
相关文章推荐
- 详解Android应用中屏幕尺寸的获取及dp和px值的转换
- 基于Android中dp和px之间进行转换的实现代码
- Android中dip、dp、sp、pt和px的区别详解
- LFC1.0.0 版本发布
- Android dpi,dip,dp的概念以及屏幕适配
- Android px、dp、sp之间相互转换
- HP data protector软件学习1--基本角色与基本工作流程
- HP data protector软件学习2--软件组成与界面介绍
- android中像素单位dp、px、pt、sp的比较
- Android对px和dip进行尺寸转换的方法
- Android根据分辨率进行单位转换-(dp,sp转像素px)
- android 尺寸 dp,sp,px,dip,pt详解
- DP问题各种模型的状态转移方程
- POJ-1695-Magazine Delivery-dp
- nyoj-1216-整理图书-dp
- TYVJ1193 括号序列解题报告
- 对DP的一点感想
- TYVJ上一些DP的解题报告
- soj1005. Roll Playing Games
- 01背包问题