hdu3450Counting Sequences 树状数组

//给一串序列,找出长度大于2,且相邻两个数的差值不大于d的数子序列的个数
//dp[u] 表示以u为最后一个点满足条件的序列个数
//dp[u] = segma(dp[v] + 1) a[u] - a[v] <= d ;
//将用树状数组来找这个求和
//不过由于没有给a[i] , 所以需要对每个数编号,然后用二分找其对应的编号
#include
#include
#include
#include
using namespace std ;
const int maxn = 100010 ;
const int mod = 9901 ;
const int inf = 1<<30 ;
int tree[maxn] ;
int a[maxn] ,len ,b[maxn];
void update(int x , int dx)
{
    while(x < maxn)
    {
        tree[x] = (tree[x] + dx)%mod ;
        x += x&(-x) ;
    }
}
int getsum(int x)
{
    int sum = 0 ;
    while(x > 0)
    {
        sum = (sum + tree[x])%mod ;
        x -= x&(-x) ;
    }
    return sum ;
}
int main()
{
    //freopen("in.txt" ,"r" , stdin) ;
    int n  , d ;
    while(~scanf("%d%d" , &n , &d))
    {
        memset(tree , 0  ,sizeof(tree)) ;
        int ans = 0 ;
        for(int i = 1;i <= n;i++)
        scanf("%d" ,&a[i]) ,b[i] = a[i] ;
        sort(a + 1 , a + 1 + n);
        len = unique(a + 1 , a+1+n)  - (a + 1);
        for(int i = 1;i <= n;i++)
        {
            int pos_1 = upper_bound(a + 1 , a + 1 + len , b[i] + d) - (a + 1) ;
            int pos_2 = lower_bound(a + 1 , a + 1 + len , b[i] - d) - (a + 1);
            int pos = lower_bound(a + 1 , a + 1 + len , b[i]) - a;
            int sum = ((getsum(pos_1) - getsum(pos_2))%mod + mod)%mod ;
            ans = (ans + sum)%mod ;
            update(pos , sum + 1) ;
        }
        printf("%d\n" , ans) ;
    }
}


你可能感兴趣的:(dp,树状数组)