hdu3450

分析:首先要知道有递推公式dp[i] = Sigma(dp[j]),dp[i]表示第i个数结尾的完美子序列的个数,|a[i] - a[j]| <= d,j<i。直接这样做的时间复杂度为n^2,对于最大有100000的n还是会超时的,留意到公式是连续加的(j<i 时,以[a[i] - d, a[i] + d]区间里面的数结尾的完美子序列个数相加),其实j>i的[a[i] - d, a[i] + d]区间里面的数结尾的完美子序列个数也可以加进去,只要初始化都为0,正因为这样可以用树状数组对这种加法进行加速,只要先用二分查找出区间两端点对应在树状数组里面的下标。

 1 #pragma warning(disable:4996)
 2 #include <cstdio>
 3 #include <set>
 4 #include <stack>
 5 #include <vector>
 6 #include <algorithm>
 7 #include <map>
 8 #define MOD 9901
 9 using namespace std;
10 int bit[100005];//bit -- binary indexed tree
11 int a[100005], order[100005], len;
12 int lowBit(int x){
13     return x & (-x);
14 }
15 //size是数组的大小,val是增量
16 void update(int idx, int size, int val){
17     while (idx <= size){
18         bit[idx] += val;
19         if (bit[idx] >= MOD){
20             bit[idx] %= MOD;
21         }
22         idx += lowBit(idx);
23     }
24 }
25 //求a[1]到a[idx]的连续子序列的和
26 int sum(int idx){
27     int ret = 0;
28     while (idx > 0){
29         ret += bit[idx];
30         if (ret >= MOD){
31             ret %= MOD;
32         }
33         idx -= lowBit(idx);
34     }
35     return ret;
36 }
37 int main(){
38     int n, d, len;
39     while (~scanf("%d%d", &n, &d)){
40         for (int i = 1; i <= n; i++){
41             scanf("%d", &a[i]);
42         }
43         copy(a + 1, a + 1 + n, order + 1);
44         sort(order + 1, order + 1 + n);
45         len = unique(order + 1, order + 1 + n) - order - 1;
46         memset(bit, 0, sizeof(bit));
47         for (int i = 1; i <= n; i++){
48             int r = upper_bound(order + 1, order + 1 + len, a[i] + d) - order - 1;
49             int l = lower_bound(order + 1, order + 1 + len, a[i] - d) - order - 1;
50             int p = lower_bound(order + 1, order + 1 + len, a[i]) - order;
51             int temp = sum(r) - sum(l);
52             temp = (temp % MOD + MOD) % MOD;
53             update(p, len, temp + 1);
54         }
55         printf("%d\n", ((sum(len) - n) % MOD + MOD) % MOD);
56     }
57     return 0;
58 }

 

转载于:https://www.cnblogs.com/ZShogg/p/3553816.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值