1. 程式人生 > >hdu3450Counting Sequences DP+樹狀陣列

hdu3450Counting Sequences DP+樹狀陣列

 

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;
}