zoukankan      html  css  js  c++  java
  • 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
    ", ans % MOD );
    74     }
    75     return 0;
    76 }
  • 相关阅读:
    Gradle在大型Java项目上的应用
    2015年,移动开发都有哪些热点?
    为什么寄存器比内存快?
    Gogs:可能是比Gitlab更好的选择
    自定义元素–为你的HTML代码定义新元素
    在DLL编程中,导出函数为什么需要extern "C"
    c调用c++编的dll,c++调用c编写的dll,extern “C”的用法
    C/C++:函数的编译方式与调用约定以及extern “C”的使用
    在VS2015中用C++编写可被其它语言调用的动态库DLL
    C++在VS下创建、调用dll
  • 原文地址:https://www.cnblogs.com/GBRgbr/p/3197983.html
Copyright © 2011-2022 走看看