码迷,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
迷上了代码!