HDU  1698

链接:  http://acm.hdu.edu.cn/showproblem.php?pid=1698

线段树功能:update:成段替换 (由于只query一次总区间,所以可以直接输出1结点的信息)

  1. <span style="font-size:18px;">#include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #define lson l,m,rt<<1
  5. #define rson m+1,r,rt<<1|1
  6. using namespace std;
  7. const int maxn=100001;
  8. int sum[maxn<<2];
  9. int col[maxn<<2];
  10. void pushUP(int rt) //当前节点信息更新给父节点
  11. {
  12. sum[rt]=sum[rt<<1]+sum[rt<<1|1];
  13. }
  14. void pushdown(int rt,int m) //当前节点信息更新给儿子节点
  15. {
  16. if(col[rt])
  17. {
  18. col[rt<<1]=col[rt<<1|1]=col[rt];
  19. sum[rt<<1]=(m-(m>>1))*col[rt];
  20. sum[rt<<1|1]=(m>>1)*col[rt];
  21. col[rt]=0;
  22. }
  23. }
  24. void build(int l,int r,int rt) //建立线段树
  25. {
  26. col[rt]=0;
  27. sum[rt]=1;
  28. if(l==r)
  29. return;
  30. int m=(l+r)/2;
  31. build(lson);
  32. build(rson);
  33. pushUP(rt);
  34. }
  35. void update(int L,int R,int c,int l,int r,int rt) //成段替换,由于只query一次总区间,所以可以直接输出1节点的信息
  36. {
  37. if(L<=l&&r<=R)
  38. {
  39. col[rt]=c;
  40. sum[rt]=(r-l+1)*c;
  41. return;
  42. }
  43. pushdown(rt,r-l+1);
  44. int m=(l+r)/2;
  45. if(L<=m) update(L,R,c,lson);
  46. if(R>m) update(L,R,c,rson);
  47. pushUP(rt);
  48. }
  49. int main()
  50. {
  51. int T,n,m;
  52. scanf("%d",&T);
  53. for(int cas=1;cas<=T;cas++)
  54. {
  55. scanf("%d%d",&n,&m);
  56. build(1,n,1);;
  57. while(m--)
  58. {
  59. int a,b,c;
  60. scanf("%d%d%d",&a,&b,&c);
  61. update(a,b,c,1,n,1);
  62. }
  63. printf("Case %d: The total value of the hook is %d.\n",cas , sum[1]);
  64. }
  65. return 0;
  66. }</span>

poj 3468

链接:http://poj.org/problem?id=3468

题解:很好的一个区间更新的线段树的模型,线段树的功能,update成段增减,query区间求和,关键在于对pushdown的理解,当扩展区间与节点上区间完全吻合时,停止向下

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #define lson l,m,rt<<1
  5. #define rson m+1,r,rt<<1|1
  6. using namespace std;
  7. const int maxn=100001;
  8. long long sum[maxn<<2],col[maxn<<2];
  9. void pushUP(int rt)
  10. {
  11. sum[rt]=sum[rt<<1]+sum[rt<<1|1];
  12. }
  13. void pushdown(int rt,int m)
  14. {
  15. if(col[rt])
  16. {
  17. col[rt<<1]+=col[rt];
  18. col[rt<<1|1]+=col[rt];
  19. sum[rt<<1]+=(m-(m>>1))*col[rt];
  20. sum[rt<<1|1]+=(m>>1)*col[rt];
  21. col[rt]=0;
  22. }
  23. }
  24. void build(int l,int r,int rt)
  25. {
  26. col[rt]=0;
  27. if(l==r)
  28. {
  29. scanf("%lld",&sum[rt]);
  30. return;
  31. }
  32. int m=(l+r)/2;
  33. build(lson);
  34. build(rson);
  35. pushUP(rt);
  36. }
  37. void update(int L,int R,int c,int l,int r,int rt) //成段增减
  38. {
  39. if(L<=l&&r<=R)
  40. {
  41. col[rt]+=c;
  42. sum[rt]+=c*(r-l+1);
  43. return;
  44. }
  45. pushdown(rt,r-l+1);
  46. int m=(l+r)/2;
  47. if(L<=m) update(L,R,c,lson);
  48. if(R>m) update(L,R,c,rson);
  49. pushUP(rt);
  50. }
  51. long long query(int L,int R,int l,int r,int rt) //区间求和
  52. {
  53. if(L<=l&&r<=R)
  54. return sum[rt];
  55. pushdown(rt,r-l+1);
  56. long long ret=0;
  57. int m=(l+r)/2;
  58. if(L<=m) ret+=query(L,R,lson);
  59. if(R>m) ret+=query(L,R,rson);
  60. return ret;
  61. }
  62. int main()
  63. {
  64. int n,q;
  65. scanf("%d%d",&n,&q);
  66. build(1,n,1);
  67. while(q--)
  68. {
  69. int a,b,c;
  70. char op[2];
  71. scanf("%s",op);
  72. if(op[0]=='Q')
  73. {
  74. scanf("%d%d",&a,&b);
  75. printf("%lld\n",query(a,b,1,n,1));
  76. }
  77. else
  78. {
  79. scanf("%d%d%d",&a,&b,&c);
  80. update(a,b,c,1,n,1);
  81. }
  82. }
  83. return 0;
  84. }

poj2528(线段树+离散化)

题目链接:http://poj.org/problem?id=2528

题目解答:

离散化就是压缩区间,使原有的长区间映射到新的短区间,但是区间压缩前后的覆盖关系不变。举个例子:

有一条1到10的数轴(长度为9),给定4个区间[2,4] [3,6] [8,10] [6,9],覆盖关系就是后者覆盖前者,每个区间染色依次为 1 2 3 4。

现在我们抽取这4个区间的8个端点,2 4 3 6 8 10 6 9

然后删除相同的端点,这里相同的端点为6,则剩下2 4 3 6 8 10 9

对其升序排序,得2 3 4 6 8 9 10

然后建立映射

2     3     4     6     8     9   10

↓     ↓      ↓     ↓     ↓     ↓     ↓

1     2     3     4     5     6     7

那么新的4个区间为 [1,3] [2,4] [5,7] [4,6],覆盖关系没有被改变。新数轴为1到7,即原数轴的长度从9压缩到6,显然构造[1,7]的线段树比构造[1,10]的线段树更省空间,搜索也更快,但是求解的结果却是一致的。

离散化时有一点必须要注意的,就是必须先剔除相同端点后再排序,这样可以减少参与排序元素的个数,节省时间。

由于此题数据较大,所以此题要用离散化

线段树功能:update:成段替换 query:简单hash

  1. #include<iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <algorithm>
  5. using namespace std;
  6. #define lson l , m , rt << 1
  7. #define rson m + 1 , r , rt << 1 | 1
  8. const int maxn = 11111;
  9. bool hash[maxn];
  10. int li[maxn] , ri[maxn];
  11. int X[maxn*3];
  12. int col[maxn<<4];
  13. int cnt;
  14. void PushDown(int rt) //更新到儿子节点(此处为覆盖,所以用这种方法更新)
  15. {
  16. if (col[rt] != -1)
  17. {
  18. col[rt<<1] = col[rt<<1|1] = col[rt];
  19. col[rt] = -1;
  20. }
  21. }
  22. void update(int L,int R,int c,int l,int r,int rt) //成段替换
  23. {
  24. if (L <= l && r <= R) {
  25. col[rt] = c;
  26. return ;
  27. }
  28. PushDown(rt);
  29. int m = (l + r) >> 1;
  30. if (L <= m) update(L , R , c , lson);
  31. if (m < R) update(L , R , c , rson);
  32. }
  33. void query(int l,int r,int rt) //简单的hash,cnt统计离散化以后的长度
  34. {
  35. if (col[rt] != -1)
  36. {
  37. if (!hash[col[rt]]) cnt ++;
  38. hash[ col[rt] ] = true;
  39. return ;
  40. }
  41. if (l == r) return ;
  42. int m = (l + r) >> 1;
  43. query(lson);
  44. query(rson);
  45. }
  46. int Bin(int key,int n,int X[]) //二分查找的过程
  47. {
  48. int l = 0 , r = n - 1;
  49. while (l <= r)
  50. {
  51. int m = (l + r) >> 1;
  52. if (X[m] == key) return m;
  53. if (X[m] < key) l = m + 1;
  54. else r = m - 1;
  55. }
  56. return -1;
  57. }
  58. int main()
  59. {
  60. int T , n;
  61. scanf("%d",&T);
  62. while (T --)
  63. {
  64. scanf("%d",&n);
  65. int nn = 0;
  66. for (int i = 0 ; i < n ; i ++) //离散化的过程
  67. {
  68. scanf("%d%d",&li[i] , &ri[i]);
  69. X[nn++] = li[i];
  70. X[nn++] = ri[i];
  71. }
  72. sort(X , X + nn);
  73. int m = 1;
  74. for (int i = 1 ; i < nn; i ++)
  75. {
  76. if (X[i] != X[i-1]) X[m ++] = X[i];
  77. }
  78. for (int i = m - 1 ; i > 0 ; i --)
  79. {
  80. if (X[i] != X[i-1] + 1) X[m ++] = X[i-1] + 1;
  81. }
  82. sort(X , X + m);
  83. memset(col , -1 , sizeof(col));
  84. for (int i = 0 ; i < n ; i ++)
  85. {
  86. int l = Bin(li[i], m, X);
  87. int r = Bin(ri[i], m, X);
  88. update(l, r, i, 0, m - 1, 1);
  89. }
  90. cnt = 0;
  91. memset(hash, false, sizeof(hash));
  92. query(0, m - 1, 1);
  93. printf("%d\n",cnt);
  94. }
  95. return 0;
  96. }

线段树之成段更新( 需要用到延迟标记,简单来说就是每次更新的时候不要更新到底,用延迟标记使得更新延迟到下次需要更新or询问到的时候)的更多相关文章

  1. Codeforces295A - Greg and Array(线段树的成段更新)

    题目大意 给定一个序列a[1],a[2]--a[n] 接下来给出m种操作,每种操作是以下形式的: l r d 表示把区间[l,r]内的每一个数都加上一个值d 之后有k个操作,每个操作是以下形式的: x ...

  2. hdu 1698 Just a Hook(线段树之 成段更新)

    Just a Hook                                                                             Time Limit: ...

  3. hdu 4614 Vases and Flowers(线段树:成段更新)

    线段树裸题.自己写复杂了,准确说是没想清楚就敲了. 先是建点为已插花之和,其实和未插花是一个道理,可是开始是小绕,后来滚雪球了,跪了. 重新建图,分解询问1为:找出真正插画的开始点和终止点,做成段更新 ...

  4. POJ 2777 Count Color(线段树之成段更新)

    Count Color Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 33311 Accepted: 10058 Descrip ...

  5. POJ3648 A Simple Problem with Integers(线段树之成段更新。入门题)

    A Simple Problem with Integers Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 53169 Acc ...

  6. hdu1698 Just a Hook 线段树:成段替换,总区间求和

    转载请注明出处:http://blog.csdn.net/u012860063 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1698 Problem ...

  7. hdu 1698 线段树(成段替换 区间求和)

    一条钩子由许多小钩子组成 更新一段小钩子 变成铜银金 价值分别变成1 2 3 输出最后的总价值 Sample Input11021 5 25 9 3 Sample OutputCase 1: The ...

  8. POJ 3468 A Simple Problem with Integers //线段树的成段更新

    A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 59046   ...

  9. poj2528 Mayor's posters(线段树之成段更新)

    Mayor's posters Time Limit: 1000MSMemory Limit: 65536K Total Submissions: 37346Accepted: 10864 Descr ...

随机推荐

  1. Lighttpd 服务器的安装

    https://www.cnblogs.com/rongfengliang/articles/3503228.html

  2. AC日记——栈 洛谷 P1044

    题目背景 栈是计算机中经典的数据结构,简单的说,栈就是限制在一端进行插入删除操作的线性表. 栈有两种最重要的操作,即pop(从栈顶弹出一个元素)和push(将一个元素进栈). 栈的重要性不言自明,任何 ...

  3. es6 递归 tree

    function loop(data) { let office = data.map(item => { if(item.type == '1' ||item.type == '2') { i ...

  4. python异常捕获异常堆栈输出

    python异常捕获异常堆栈输出 学习了:https://blog.csdn.net/chris_grass/article/details/77927902 import traceback def ...

  5. hadoop2.7.1 nutch2.3 二次开发windows环境

     Hadoop windows编译: 能够略过这一段,直接下载hadoo2.7.1 bin文件.我的资源里有终于生成的winutils.exe和一些native code,放在bin文件夹即可了 參 ...

  6. HTML5已定稿:将彻底颠覆原生应用

    2007年W3C(万维网联盟)立项HTML5,直至2014年10月底.这个长达八年的规范最终正式封稿. 过去这些年.HTML5颠覆了PC互联网的格局,优化了移动互联网的体验,接下来.HTML5将颠覆原 ...

  7. 关于文件与文件系统的压缩与打包命令-Linux(笔记)

    1.gzip : 压缩命令 gzip [-cdtv#] 文件名称 (后缀为.gz) -c :将压缩的数据输出到屏幕上,可通过数据流重定向处理 -d : 解压缩的參数 -v : 能够显示源文件/压缩文件 ...

  8. OpenStack Live Migration

    About live migration of KVM virtual machines with NFS storage, from Mirantis blog: click this link w ...

  9. 作为iOS程序员,最核心的60%能力有哪些?

    作为iOS程序员,最核心的60%能力有哪些?   一个合格的iOS程序员需要掌握多少核心技能?你和专业的开发工程师的差距有多大?你现在的水平能开发一个功能完整性能高效的iOS APP吗?一起来看看下面 ...

  10. 给大二学生——能够再坚持一年的ACM

    [来信] 我是大二学生,就读于一所非常普通的大学.学校ACM基本零起步,去年才開始搞,我大一大二花了非常多时间搞acm,如今不太想放弃.但学校基本没人愿意搞这个. 非常快就要大三了,我一直在纠结要不要 ...