HDU 2836 Traversal 简单DP + 树状数组

题意:给你一个序列,问相邻两数高度差绝对值小于等于H的子序列有多少个。

dp[i]表示以i为结尾的子序列有多少,易知状态转移方程为:dp[i] = sum( dp[j] ) + 1;( abs( height[i] - height[j] ) <= H )

由abs( height[i] - height[j] ) <= H 可得 height[i] - H <= height[j] <= height[i] + H

将序列中的数离散化,每个height对应一个id, 用树状数组求区间[ height[i] - H的id, height[i] + H的id ]内dp[j]的和,并且每次把新得到的dp[i]更新到树状数组中height[i]的id对应的位置。

 

 1 #include <cstdio>

 2 #include <cstring>

 3 #include <cstdlib>

 4 #include <algorithm>

 5 

 6 using namespace std;

 7 

 8 const int MAXN = 100100;

 9 const int MOD = 9901;

10 

11 int dp[MAXN];

12 int height[MAXN];

13 int num[MAXN];

14 int C[MAXN];

15 int n, d;

16 

17 int lowbit( int x )

18 {

19     return x & ( -x );

20 }

21 

22 int Query( int x )

23 {

24     int res = 0;

25     while ( x > 0 )

26     {

27         res += C[x];

28         res %= MOD;

29         x -= lowbit(x);

30     }

31     return res;

32 }

33 

34 void Add( int x, int v )

35 {

36     while ( x <= n )

37     {

38         C[x] += v;

39         C[x] %= MOD;

40         x += lowbit(x);

41     }

42     return;

43 }

44 

45 int main()

46 {

47     while ( ~scanf( "%d%d", &n, &d ) )

48     {

49         for ( int i = 1; i <= n; ++i )

50         {

51             scanf( "%d", &height[i] );

52             num[i] = height[i];

53         }

54 

55         sort( num + 1, num + n + 1 );

56         int cnt = unique( num + 1, num + n + 1 ) - num - 1;

57 

58         memset( C, 0, sizeof(C) );

59         int ans = 0;

60         dp[0] = 0;

61         for ( int i = 1; i <= n; ++i )

62         {

63             int id = lower_bound( num + 1, num + cnt + 1, height[i] ) - num;

64             int left = lower_bound( num + 1, num + cnt + 1, height[i] - d ) - num;

65             int right = upper_bound( num + 1, num + cnt + 1, height[i] + d ) - num - 1;

66             dp[i] = ( Query( right ) - Query( left - 1 ) + 1 ) % MOD;

67             ans += dp[i];

68             Add( id, dp[i] );

69         }

70 

71         if ( ans >= n ) ans -= n;

72         else ans = 0;

73         printf("%d\n", ans % MOD );

74     }

75     return 0;

76 }

 

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