码迷,mamicode.com
首页 > 其他好文 > 详细

线段树

时间:2015-07-19 18:11:49      阅读:173      评论:0      收藏:0      [点我收藏+]

标签:acm   summary   

线段树

1.线段树最裸模板

Problem I

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdio>
  4. using namespace std;
  5. const int MAX=50010;
  6. #define Lson L,mid,root<<1 //遇到Lson的时候强制替换为后面的语句
  7. #define Rson mid+1,R,root<<1|1
  8. int n,sum[MAX<<2];
  9. void Pushup(int root) //把当前结点的信息更新到父节点
  10. {
  11. sum[root]=sum[root<<1]+sum[root<<1|1];
  12. }
  13. void Build(int L,int R,int root)
  14. {
  15. if(L==R)
  16. {
  17. scanf("%d",&sum[root]);
  18. return ;
  19. }
  20. int mid=(L+R)>>1;
  21. Build(Lson); //左孩子
  22. Build(Rson); //右孩子
  23. Pushup(root);
  24. }
  25. void Update(int q,int val,int L,int R,int root) //在根为root,区间为[L,R]中的线段树修改结点p的值增加val
  26. {
  27. if(L==R)
  28. {
  29. sum[root]+=val;
  30. return ;
  31. }
  32. int mid=(L+R)>>1;
  33. if(q<=mid) Update(q,val,Lson); //说明p在左结点
  34. else Update(q,val,Rson); //说明p在右结点
  35. Pushup(root);
  36. }
  37. int Query(int l, int r, int L, int R, int root)
  38. {
  39. if(l==L && r==R)
  40. return sum[root];
  41. int mid = (L + R) >> 1;
  42. if(r <= mid) return Query(l, r, Lson);
  43. else if(l > mid) return Query(l, r, Rson);
  44. else return Query(l, mid, Lson) + Query(mid+1, r, Rson);
  45. }
  46. int main()
  47. {
  48. int a,b,Case,num=1;
  49. scanf("%d",&Case);
  50. while(Case--)
  51. {
  52. printf("Case %d:\n",num++);
  53. scanf("%d",&n);
  54. Build(1,n,1);
  55. char op[10];
  56. while(scanf("%s",op))
  57. {
  58. if(op[0]==‘E‘) break;
  59. scanf("%d%d",&a,&b);
  60. if(op[0]==‘A‘) Update(a,b,1,n,1);
  61. if(op[0]==‘S‘) Update(a,-b,1,n,1);
  62. if(op[0]==‘Q‘) printf("%d\n",Query(a,b,1,n,1));
  63. }
  64. }
  65. return 0;
  66. }

2.线段树区间修改---Lazy大法

Problem II

  1. #include <cstdio>
  2. #include <cstring>
  3. #define maxn 100000 + 10
  4. #define Lson L, mid, rt<<1
  5. #define Rson mid+1, R, rt<<1|1
  6. struct Node
  7. {
  8. int sum, lazy;
  9. } T[maxn<<2];
  10. void PushUp(int rt)
  11. {
  12. T[rt].sum = T[rt<<1].sum + T[rt<<1|1].sum;
  13. }
  14. void PushDown(int L, int R, int rt)
  15. {
  16. int mid = (L + R) >> 1;
  17. T[rt<<1].sum = T[rt].lazy * (mid - L + 1);
  18. T[rt<<1|1].sum = T[rt].lazy * (R - mid);
  19. T[rt<<1].lazy = T[rt].lazy;
  20. T[rt<<1|1].lazy = T[rt].lazy;
  21. T[rt].lazy = 0;
  22. }
  23. void Build(int L, int R, int rt)
  24. {
  25. if(L == R)
  26. {
  27. scanf("%d", &T[rt].sum);
  28. return ;
  29. }
  30. int mid = (L + R) >> 1;
  31. Build(Lson);
  32. Build(Rson);
  33. PushUp(rt);
  34. }
  35. void Update(int l, int r, int v, int L, int R, int rt)
  36. {
  37. if(l==L && r==R)
  38. {
  39. T[rt].lazy = v;
  40. T[rt].sum = v * (R - L + 1);
  41. return ;
  42. }
  43. int mid = (L + R) >> 1;
  44. if(T[rt].lazy) PushDown(L, R, rt);
  45. if(r <= mid) Update(l, r, v, Lson);
  46. else if(l > mid) Update(l, r, v, Rson);
  47. else
  48. {
  49. Update(l, mid, v, Lson);
  50. Update(mid+1, r, v, Rson);
  51. }
  52. PushUp(rt);
  53. }
  54. int Query(int l, int r, int L, int R, int rt)
  55. {
  56. if(l==L && r== R)
  57. return T[rt].sum;
  58. int mid = (L + R) >> 1;
  59. if(T[rt].lazy) PushDown(L, R, rt);
  60. if(r <= mid) return Query(l, r, Lson);
  61. else if(l > mid) return Query(l, r, Rson);
  62. return Query(l, mid, Lson) + Query(mid + 1, r, Rson);
  63. }
  64. int main()
  65. {
  66. int n, q;
  67. scanf("%d", &n);
  68. Build(1, n, 1);
  69. scanf("%d", &q);
  70. int a, b, c, d;
  71. while(q--)
  72. {
  73. scanf("%d%d%d", &a, &b, &c);
  74. if(a)
  75. {
  76. scanf("%d", &d);
  77. Update(b, c, d, 1, n, 1);
  78. }
  79. else printf("%d\n", Query(b, c, 1, n, 1));
  80. }
  81. return 0;
  82. }

3.离散化 + 线段树

Problem III

离散型与连续型的区别: 
1.叶子节点:在离散型中,叶子节点是[i, i],而连续性中是[i, i + 1]; 
2.分解区间:在离散型中,一段区间是分解成为[l, m], [m + 1, r],而在连续型中,是分解成为[l, m], [m, r]; 
3.其他所有类似的判定问题。

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <set>
  5. #include <map>
  6. using namespace std;
  7. #define maxn 100005
  8. #define lson L, mid, rt<<1
  9. #define rson mid, R, rt<<1|1
  10. int a[maxn], b[maxn];
  11. int lazy[maxn<<2];
  12. int N, L;
  13. int left_bound = 1, right_bound;
  14. void init()
  15. {
  16. memset(lazy, -1, sizeof(lazy));
  17. right_bound = 0;
  18. }
  19. void read_compress()
  20. {
  21. set<int> s;
  22. for(int i=1; i<=N; i++)
  23. {
  24. scanf("%d%d", &a[i], &b[i]);
  25. s.insert(a[i]);
  26. s.insert(b[i]);
  27. }
  28. map<int, int> m;
  29. for(set<int>::iterator it=s.begin(); it!=s.end(); it++)
  30. m[*it] = ++right_bound;
  31. for(int i=1; i<=N; i++)
  32. {
  33. a[i] = m[a[i]];
  34. b[i] = m[b[i]];
  35. }
  36. }
  37. void pushdown(int L, int R, int rt)
  38. {
  39. if(lazy[rt] >= 0)
  40. lazy[rt<<1] = lazy[rt<<1|1] = lazy[rt];
  41. lazy[rt] = -1;
  42. }
  43. void update(int l, int r, int v, int L, int R, int rt)
  44. {
  45. if(l==L && r==R)
  46. {
  47. lazy[rt] = v;
  48. return ;
  49. }
  50. int mid = (L+R)>>1;
  51. if(lazy[rt] >= 0) pushdown(L, R, rt);
  52. if(r <= mid) update(l, r, v, lson);
  53. else if(l >= mid) update(l, r, v, rson);
  54. else
  55. {
  56. update(l, mid, v, lson);
  57. update(mid, r, v, rson);
  58. }
  59. }
  60. void query(int l, int r, int L, int R, int rt, set<int> &s)
  61. {
  62. if(l==L && r==R && lazy[rt]>=0)
  63. {
  64. s.insert(lazy[rt]);
  65. return ;
  66. }
  67. int mid = (L+R)>>1;
  68. if(lazy[rt] >= 0) pushdown(L, R, rt);
  69. if(r <= mid) query(l, r, lson, s);
  70. else if(l >= mid) query(l, r, rson, s);
  71. else
  72. {
  73. query(l, mid, lson, s);
  74. query(mid, r, rson, s);
  75. }
  76. }
  77. int main()
  78. {
  79. while(~scanf("%d%d", &N, &L))
  80. {
  81. init();
  82. read_compress();
  83. int cnt = 0;
  84. for(int i=1; i<=N; i++)
  85. update(a[i], b[i], ++cnt, left_bound, right_bound, 1);
  86. cnt = 0;
  87. set<int> s;
  88. for(int i=1; i<=N; i++)
  89. query(a[i], b[i], left_bound, right_bound, 1, s);
  90. printf("%d\n", s.size());
  91. }
  92. return 0;
  93. }

4.相关内容

The New 
Go For it

5.由2延伸修改

线段树区间修改 维护和值、最大值、最小值

  1. #include <cstdio>
  2. #include <cstring>
  3. #define maxn 100000 + 10
  4. #define Lson L, mid, rt<<1
  5. #define Rson mid+1, R, rt<<1|1
  6. int min(int a, int b) {return a<b ? a : b;}
  7. int max(int a, int b) {return a>b ? a : b;}
  8. struct Node
  9. {
  10. int sum, Min, Max, lazy;
  11. } T[maxn<<2];
  12. void PushUp(int rt)
  13. {
  14. T[rt].sum = T[rt<<1].sum + T[rt<<1|1].sum;
  15. T[rt].Min = min(T[rt<<1].Min, T[rt<<1|1].Min);
  16. T[rt].Max = max(T[rt<<1].Max, T[rt<<1|1].Max);
  17. }
  18. void PushDown(int L, int R, int rt)
  19. {
  20. int mid = (L + R) >> 1;
  21. int t = T[rt].lazy;
  22. T[rt<<1].sum = t * (mid - L + 1);
  23. T[rt<<1|1].sum = t * (R - mid);
  24. T[rt<<1].Min = T[rt<<1|1].Min = t;
  25. T[rt<<1].Max = T[rt<<1|1].Max = t;
  26. T[rt<<1].lazy = T[rt<<1|1].lazy = t;
  27. T[rt].lazy = 0;
  28. }
  29. void Build(int L, int R, int rt)
  30. {
  31. if(L == R)
  32. {
  33. scanf("%d", &T[rt].sum);
  34. T[rt].Min = T[rt].Max = T[rt].sum;
  35. return ;
  36. }
  37. int mid = (L + R) >> 1;
  38. Build(Lson);
  39. Build(Rson);
  40. PushUp(rt);
  41. }
  42. void Update(int l, int r, int v, int L, int R, int rt)
  43. {
  44. if(l==L && r==R)//修改区间值
  45. {
  46. T[rt].lazy = v;
  47. T[rt].sum = v * (R - L + 1);
  48. T[rt].Min = T[rt].Max = v;
  49. return ;
  50. }
  51. int mid = (L + R) >> 1;
  52. if(T[rt].lazy) PushDown(L, R, rt);//向下更新一级
  53. if(r <= mid) Update(l, r, v, Lson);
  54. else if(l > mid) Update(l, r, v, Rson);
  55. else
  56. {
  57. Update(l, mid, v, Lson);
  58. Update(mid+1, r, v, Rson);
  59. }
  60. PushUp(rt);
  61. }
  62. int Query(int l, int r, int L, int R, int rt)
  63. {
  64. if(l==L && r== R)
  65. {
  66. printf("(%d, %d)---Min: %d Max: %d Sum: %d \n", L, R, T[rt].Min, T[rt].Max, T[rt].sum);
  67. return T[rt].sum;
  68. }
  69. int mid = (L + R) >> 1;
  70. if(T[rt].lazy) PushDown(L, R, rt);
  71. if(r <= mid) return Query(l, r, Lson);
  72. else if(l > mid) return Query(l, r, Rson);
  73. return Query(l, mid, Lson) + Query(mid + 1, r, Rson);
  74. }
  75. int main()
  76. {
  77. int n, q;
  78. scanf("%d", &n);
  79. Build(1, n, 1);
  80. scanf("%d", &q);
  81. int a, b, c, d;
  82. while(q--)
  83. {
  84. scanf("%d%d%d", &a, &b, &c);
  85. if(a)
  86. {
  87. scanf("%d", &d);
  88. Update(b, c, d, 1, n, 1);
  89. }
  90. else printf("%d\n", Query(b, c, 1, n, 1));
  91. }
  92. return 0;
  93. }
  94. /*
  95. 6
  96. 1 2 3 4 5 6
  97. 3
  98. 0 1 4
  99. 1 2 3 0
  100. 0 1 4
  101. */

版权声明:本文为博主原创文章,未经博主允许不得转载。

线段树

标签:acm   summary   

原文地址:http://blog.csdn.net/dojintian/article/details/46955583

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!