hdu3450Counting Sequences DP+树状数组

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sdz20172133/article/details/86243066
 

Counting Sequences

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/65536 K (Java/Others)
Total Submission(s): 3012    Accepted Submission(s): 1067


 

Problem Description

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.

 

Input

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

 

Output

The number of Perfect Sub-sequences mod 9901

 

Sample Input

 

4 2 1 3 7 5

 

Sample Output

 

4

 

Source

2010 ACM-ICPC Multi-University Training Contest(2)——Host by BUPT

 

Recommend

We have carefully selected several similar problems for you:  1541 1394 2838 3030 2227 

 

Statistic | Submit | Discuss | Note

题意:

给出一段序列,让你找出一段子序列(长度>=2)满足序列中每相邻的两个数之间的差 <=d,求出这样的序列的个数。

分析:

首先我们可以看出是一个DP,我们设dp[i]表示以a[i]为结尾的满足条件序列的个数。

状态转移方程:

dp[i]=\sumdp[j]  +  1     |a[i]-a[j]|<=d

接下来就是如何取出【a[i]-d,a[i]+d】区间里的所有dp,暴力肯定超时,树状数组去维护。

当然这题还需要离散化,数据量过大,我们在树状数组存相应的编号就行。

#include<stdio.h>
#include<string>
#include<string.h>
#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;
const int MAXN=200000+5;//最大元素个数
int d,n;//元素个数
ll c[MAXN];
int a[MAXN],b[MAXN];//c[i]==A[i]+A[i-1]+...+A[i-lowbit(i)+1]
//返回i的二进制最右边1的值
int lowbit(int i)
{
    return i&(-i);
}
//返回A[1]+...A[i]的和
ll sum(int x){
    ll sum = 0;
    while(x){
        sum += c[x];
        x -= lowbit(x);
    }
    return sum;
}
//令A[i] += val
void add(int x, ll val){
	
    while(x <= n){
        c[x] += val;
        x += lowbit(x);
    }
}
const int mod=9901;
int main()
{
	while(scanf("%d%d",&n,&d)!=-1)
	{
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&a[i]);
			b[i]=a[i];
		}
		sort(a+1,a+n+1);
		int len=unique(a+1,a+n+1)-a-1;
		memset(c,0,sizeof(c));
		int ans=0;
		for(int i=1;i<=n;i++)
		{
			int pos1=upper_bound(a+1,a+1+len,b[i]+d)-(a+1); ///右界
			
			int pos2=lower_bound(a+1,a+1+len,b[i]-d)-(a+1);///左界
			int pos=lower_bound(a+1,a+1+len,b[i])-a;       ///本身位置
			ll sum1=((sum(pos1)-sum(pos2))%mod+mod)%mod;   ///查询以a[i]为结尾的完美序列
			ans=(ans+sum1)%mod;
			add(pos,sum1+1);
		}
		cout<<ans<<endl;
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/sdz20172133/article/details/86243066