zoukankan      html  css  js  c++  java
  • hdu 2227 dp+树状数组优化

    很容易可以想到状态转移方程:

      dp[i] = segma: dp[j] ( j < i && a[j] <= a[i] ), 其中dp[i]表示以a[i]结尾的不降子序列的个数。

    但是n非常大,n^2的算法必然TLE,仔细想想其实式子右边是一个区间和的形式,即小于等于a[i]的a[j]的dp[j]的和,所以可以将a[i]离散化成t后将dp[i]的值存在t位置上,每次求解dp[i]就是查询一个前缀和,可以用树状数组来维护。

    举个例子:对于1,50,13,34这四个数,离散化后变成了1,4,2,3。显然dp[1] = 1,所以我们在1位置插入1;而dp[2]就等于查询位置1到4(1+0+0+0)的和再加1,所以dp[2] = 2,我们在4位置插入2;dp[3]就等于(1+0)再加1,dp[3] = 2,我们在2位置插入2;dp[4]就等于(1+2+0)再加1为4,在位置3插入4,最后答案为整个数列的和:1+2+4+2=9.

     1 #include <algorithm>
     2 #include <iostream>
     3 #include <cstring>
     4 #include <cstdio>
     5 using namespace std;
     6 
     7 typedef long long ll;
     8 const int N = 100001;
     9 const int MOD = 1000000007;
    10 int c[N];
    11 
    12 struct Node 
    13 {
    14     ll s;
    15     int id;    
    16 } node[N];
    17 
    18 int lb( int i )
    19 {
    20     return i & -i;
    21 }
    22 
    23 void set( int i, int x )
    24 {
    25     while ( i < N )
    26     {
    27         c[i] += x;
    28         c[i] %= MOD;
    29         i += lb(i);
    30     }
    31 }
    32 
    33 int get( int i )
    34 {
    35     int ans = 0;
    36     while ( i > 0 )
    37     {
    38         ans += c[i];
    39         ans %= MOD;
    40         i -= lb(i);
    41     }
    42     return ans;
    43 }
    44 
    45 bool cmp1( Node n1, Node n2 )
    46 {
    47     if ( n1.s != n2.s ) return n1.s < n2.s;
    48     return n1.id < n2.id;
    49 }
    50 
    51 bool cmp2( Node n1, Node n2 )
    52 {
    53     return n1.id < n2.id;    
    54 }
    55 
    56 int main ()
    57 {
    58     int n;
    59     while ( scanf("%d", &n) != EOF )
    60     {
    61         for ( int i = 1; i <= n; i++ )
    62         {
    63             scanf("%I64d", &node[i].s);
    64             node[i].id = i;            
    65         }
    66         sort( node + 1, node + 1 + n, cmp1 );
    67         for ( int i = 1; i <= n; i++ )
    68         {
    69             node[i].s = i;
    70         }
    71         sort( node + 1, node + 1 + n, cmp2 );
    72         memset( c, 0, sizeof(c) );
    73         for ( int i = 1; i <= n; i++ )
    74         {
    75             int pn = node[i].s;
    76             int nn = get(pn) + 1;
    77             set( pn, nn );
    78         }
    79         printf("%d
    ", get(n));
    80     }
    81     return 0;
    82 }
  • 相关阅读:
    decimal和numeric的用法
    Asp.net之缓存(一)
    对DataList控件绑定图片的一点小结
    Asp.net Ajax初学中遇到的版本错误及求解决方案
    TreeView的动态显示及利用框架实现导航
    linux CentOS7 防火墙设置
    SpringBoot返回JSON日期格式问题
    SpringBoot上传文件大小限制
    Winform的技巧琐碎总结简单打印功能实现
    C#的基础琐碎总结事件
  • 原文地址:https://www.cnblogs.com/huoxiayu/p/4688282.html
Copyright © 2011-2022 走看看