树状数组专题(十三)之hdu3450

//题目大意:给出一个序列和d,找出所有满足相邻元素的差得绝对值<=d子序列数
//题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3450
//这里没有给出数据的大小..试了试.是比较大的.开tree数组开不了这么大
//所以使用处理2227题目的那种处理方式来做本题.
//同时还要注意和2227的区别..因为这里不可能形成单元素序列
//所以对dp[i]+1后的更新以后..要把dp[i]--才满足情况.
//还有一点要注意..因为这几个题目的数据都比较大..是对m取模
//所以中途处理的过程中.一定要注意不要超出范围..
//最好是都开城__int64保险一点..
//遇到的一个测试也提一下..__int64 a = m*m 但是m是一个int型
//的..这样子a得到的不是一个准确的值..因为m*m先把结果给m
//再给a.所以这样得到的结果是溢出的结果.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<iostream>
#include<math.h>
#include<vector>
#include<algorithm>
using namespace std;
const int MN = 100000;
__int64 tree[MN+100],dp[MN+100];
int maxn,a[MN],b[MN],n,d;
int Lowbit(int x)
{
    return x&(-x);
}
__int64 Getsum(int x)
{
    __int64 sum = 0;
    while(x)
    {
        sum += tree[x];
        sum = sum%9901;
        x -= Lowbit(x);
    }
    return sum;
}
void Updata(int x, __int64 value)
{
    if(x <= 0) x = 1;
    for(int i = x ; i <= MN ; i += Lowbit(i))
      tree[i] = (tree[i]+value)%9901;
}
int binary(int x)
{
    int l = 1,r = n;
    while(l <= r)
    {
        int mid = (l+r)/2;
        if(b[mid] < x) l = mid+1;
        if(b[mid] > x) r = mid-1;
        if(b[mid] == x) return  mid;
    }
    return l;
}
int main()
{
    while(scanf("%d%d",&n,&d) != EOF)
    {
        maxn = -1;
        memset(tree,0,sizeof(tree));
        for(int i = 1 ; i <= n ; i++)
        {
            scanf("%d",&a[i]);
            b[i] = a[i];
        }
        sort(b+1,b+n+1);
        for(int i = 1 ; i <= n ; i++)
        {
            int id = binary(a[i]);
            dp[i] = (Getsum(id) + 1)%9901;
            int id1 = binary(a[i]-d);
            int id2 = binary(a[i]+d+1);
            Updata(id1,dp[i]);
            Updata(id2,-dp[i]);
            dp[i] = (dp[i] + 9900)%9901;
        }
        __int64 ans = 0;
        for(int i = 1 ; i <= n ; i++)
        {
           // printf("%d  %d\n",i,dp[i]);
            ans += dp[i];
            ans %=  9901;
        }
        printf("%I64d\n",ans);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值