您的位置:首页 > 其它

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dp