题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=41224#problem/B

分析:可以设dp[i][j]表示以i结尾长度为j的子序列的个数,那么更新就是dp[i][j]=∑dp[k][j-1],其中k<i,而且a[k]>a[i]。而要更新dp值,可以用树状数组维护,按顺序插入序列值,那么树状数组的值就可以表示比它小的长度为j-1的所有子序列的和,这样就可以在logn的时间更新dp值了,所以总复杂度是O(n*k*logn)

树状数组有两种用途(以一维树状数组举例):   

1.单点更新,区间查询(即求和)         

单点更新时,是往树根(即c[n])拓展         

而区间查询时,是往叶子节点(即c[1])拓展   

2.区间更新,单点查询         

区间更新时,是往叶子节点(即c[1])拓展         

单点查询时,往树根(即c[n])拓展

这两个操作只不过是在update()和sum()方法中的+和-替换一下而已。

下面解释一下“区间更新时,是往叶子节点(即c[1])拓展” 和 “单点查询时,往树根(即c[n])拓展” 的原因

举例说明吧:

c[1]=a[1];

c[2]=a[1]+a[2];

c[3]=a[3];

c[4]=a[1]+a[2]+a[3]+a[4];

c[5]=a[5];

c[6]=a[5]+a[6];

c[7]=a[7];

c[8]=a[1]+...+a[8];

假如我要更新区间[3,7],那么我首先更新[1,7],即该区间+1;再更新[1,2],该区间-1:

由于更新时往叶子节点拓展的,所以更新[1,7]时:c[7]++,c[6]++,c[4]++。

可以发现,这三个正好包含了a[1]~a[7]一次,相当于a[1]~a[7]都更新一遍 而更新[1,2]时:c[2]--,包含了a[1],a[2]。

那么当我查询某一值a[i],由于是往根节点拓展,所以每个包含a[i]的c[j]都会遇到一次(更新时每个a[i]变化一次)

即之前凡是更新过的值我都会加上。

如我想查询a[2],那么a[2]=c[2]+c[4]+c[8]=-1+1+0=0;

查询a[3],那么a[3]=c[3]+c[4]+c[8]=0+1+0=1。

1)树状数组区间更新,单点求值方法

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. #define LL long long
  6. #define M 1000000000
  7. #define maxn 22222
  8. #define lson l,m,rt<<1
  9. #define rson m+1,r,rt<<1|1
  10. using namespace std;
  11. int a[maxn],c[maxn];
  12. int dp[maxn][];//dp[i][j]表示以a[i]为结尾长度为j的子序列;dp[i][j]=∑dp[k][j-1]且a[i]>a[k]
  13. int n,k;
  14. int lowbit(int x)
  15. {
  16. return x&(-x);
  17. }
  18. int sum(int i)
  19. {
  20. LL res=;
  21. while(i<=n)
  22. {
  23. res=(res+c[i])%M;
  24. i+=lowbit(i);
  25. }
  26. return res;
  27. }
  28. void update(int i,int x)
  29. {
  30. while(i)
  31. {
  32. c[i]=(c[i]+x)%M;
  33. i-=lowbit(i);
  34. }
  35. }
  36. int main()
  37. {
  38. while(scanf("%d%d",&n,&k)>)
  39. {
  40. memset(dp,,sizeof(dp));
  41. for(int i=;i<=n;i++)
  42. {
  43. scanf("%d",&a[i]);
  44. dp[a[i]][]=;
  45. }
  46. for(int i=;i<=k;i++)
  47. {
  48. memset(c,,sizeof(c));
  49. for(int j=i-;j<=n;j++)
  50. {
  51. dp[a[j]][i]=sum(a[j]);//求长度为i以a[j]点为结束的逆序对数值
  52. update(a[j],dp[a[j]][i-]);//更新处在0~a[j]的数逆序对+dp[a[j]][i-1]
  53. }
  54. }
  55. LL ans=;
  56. for(int i=;i<=n;i++)
  57. {
  58. ans=(ans+dp[a[i]][k])%M;
  59. }
  60. printf("%lld\n",ans);
  61. }
  62. }

2)树状数组单点更新,区间求值方法

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. #define LL long long
  6. #define M 1000000000
  7. #define maxn 22222
  8. #define lson l,m,rt<<1
  9. #define rson m+1,r,rt<<1|1
  10. using namespace std;
  11. int a[maxn],c[maxn];
  12. int dp[maxn][];//dp[i][j]表示以a[i]为结尾长度为j的子序列;dp[i][j]=∑dp[k][j-1]且a[i]>a[k]
  13. int n,k;
  14. int lowbit(int x)
  15. {
  16. return x&(-x);
  17. }
  18. void update(int x,int y)
  19. {
  20. while(x<=n)
  21. {
  22. c[x]=(c[x]+y)%M;
  23. x+=lowbit(x);
  24. }
  25. }
  26. int sum(int x)
  27. {
  28. int res=;
  29. while(x)
  30. {
  31. res=(res+c[x])%M;
  32. x-=lowbit(x);
  33. }
  34. return res;
  35. }
  36. int main()
  37. {
  38. while(scanf("%d%d",&n,&k)>)
  39. {
  40. for(int i=;i<=n;i++)
  41. {
  42. scanf("%d",&a[i]);
  43. dp[i][]=;
  44. }
  45. int res;
  46. for(int i=,j=n;i<j;i++,j--) res=a[i],a[i]=a[j],a[j]=res;
  47. for(int i=;i<=k;i++)
  48. {
  49. memset(c,,sizeof(c));
  50. for(int j=i-;j<=n;j++)
  51. {
  52. dp[a[j]][i]=sum(a[j]);//求在0~a[j]比a[j]小的所在点逆序对之和
  53. update(a[j],dp[a[j]][i-]);//更新a[j]点的逆序对
  54. }
  55. }
  56. int ans=;
  57. for(int i=;i<=n;i++) ans=(ans+dp[a[i]][k])%M;
  58. printf("%d\n",ans);
  59. }
  60. return ;
  61. }

URAL1523(dp+树状数组)的更多相关文章

  1. 树形DP+树状数组 HDU 5877 Weak Pair

    //树形DP+树状数组 HDU 5877 Weak Pair // 思路:用树状数组每次加k/a[i],每个节点ans+=Sum(a[i]) 表示每次加大于等于a[i]的值 // 这道题要离散化 #i ...

  2. bzoj 1264 [AHOI2006]基因匹配Match(DP+树状数组)

    1264: [AHOI2006]基因匹配Match Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 793  Solved: 503[Submit][S ...

  3. 【bzoj2274】[Usaco2011 Feb]Generic Cow Protests dp+树状数组

    题目描述 Farmer John's N (1 <= N <= 100,000) cows are lined up in a row andnumbered 1..N. The cows ...

  4. 奶牛抗议 DP 树状数组

    奶牛抗议 DP 树状数组 USACO的题太猛了 容易想到\(DP\),设\(f[i]\)表示为在第\(i\)位时方案数,转移方程: \[ f[i]=\sum f[j]\;(j< i,sum[i] ...

  5. codeforces 597C C. Subsequences(dp+树状数组)

    题目链接: C. Subsequences time limit per test 1 second memory limit per test 256 megabytes input standar ...

  6. HDU 2227 Find the nondecreasing subsequences (DP+树状数组+离散化)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2227 Find the nondecreasing subsequences             ...

  7. ccpc_南阳 C The Battle of chibi dp + 树状数组

    题意:给你一个n个数的序列,要求从中找出含m个数的严格递增子序列,求能找出多少种不同的方案 dp[i][j]表示以第i个数结尾,形成的严格递增子序列长度为j的方案数 那么最终的答案应该就是sigma( ...

  8. HDU 2838 (DP+树状数组维护带权排序)

    Reference: http://blog.csdn.net/me4546/article/details/6333225 题目链接: http://acm.hdu.edu.cn/showprobl ...

  9. [poj3378] Crazy Thairs (DP + 树状数组维护 + 高精度)

    树状数组维护DP + 高精度 Description These days, Sempr is crazed on one problem named Crazy Thair. Given N (1 ...

随机推荐

  1. chrome你这是入侵OSX了么?

    今天突然发现安装chrome的应用后,会在Dock中出现如下图标,点击即可启动chrome相关应用,很是方便.

  2. Head First PHP &amp;MySQL学习笔记

      近期一段时间在学习PHP,买了<Head First PHP&MySQL>中文版这本书,之前买过<Head First设计模式>,感觉这系列的书籍整体来说非常不错. ...

  3. strip 命令的使用方法

    用途 通过除去绑定程序和符号调试程序使用的信息,降低扩展公共对象文件格式(XCOFF)的对象文件的大小. 语法 strip [ -V ] [ -r [ -l ] | -x [ -l ] | -t | ...

  4. Swift - 使用atlas图集实现动画效果(SpriteKit游戏开发)

    我们通常继承SKSpriteNode来实现游戏中的元素,除了可以使用图片作为纹理皮肤外.我们还可以使用动画纹理集来实现动画播放. 动画纹理集的制作也很简单,首先要有一套动画序列图,然后把它们放到一个文 ...

  5. smartforms初始化

    smartforms  第一次打开的页面是和prd环境下的一样,需要跑一个程序才能编辑

  6. Servlet过滤器——过滤器分析流量

    1.概述 Servlet过滤器可以对用户提交的数据或服务器返回的数据进行更改.任何到达服务器的请求都会首先经过过滤器的处理.本实例应用过滤器的这个特点,编写了一个在过滤器中统计网站流量的实例. 本实例 ...

  7. [eclipse] 三个操作技巧

    [eclipse] 三个操作技巧 1.快捷键Ctrl+Shift+i:Debug调试中直接获取方法的返回值 在下图代码中,想知道getHost(),则在调试时运行完该句代码后,选中"urlU ...

  8. python 循环中的else

    众多语言中都有if else这对条件选择组合,但是在python中还有更多else使用的地方,比如说循环for,或者while都可以和else组合. 下面简单介绍一下for-else while-el ...

  9. 硬盘重装Ubuntu12.04的感受

    好久没更blog了,最近这两天系统也出了问题,win7蓝屏,ubuntu进不去-.后来win7整好了,ubuntu依旧顽固.用惯了linux,就不想在转到win7下面了,估计是习惯了各种敲命令的感觉吧 ...

  10. oracle 在操作blob该字段是否会产生很多redo

    操作blob该字段是否会产生很多redo,答案是否定的.以下来做一个实验,測试数据库版本号是11.2.0.1.0: --创建一张表做測试之用 create table test_blob (   id ...