POJ 3468 A Simple Problem with Integers(线段树:区间更新)
生活随笔
收集整理的這篇文章主要介紹了
POJ 3468 A Simple Problem with Integers(线段树:区间更新)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
http://poj.org/problem?id=3468
題意:
給出一串數,每次在一個區間內增加c,查詢[a,b]時輸出a、b之間的總和。
?
思路:
總結一下懶惰標記的用法吧。
比如要對一個區間范圍內的數都要加c,在找到這個區間之后,本來它的孩子結點也是需要更新的,但是我們可以暫時不更新,如果到時候需要用到這些孩子結點的時候,我們再來更新。這個時候就要用到懶惰標記了,也就是add[o]=c,之后它的孩子結點更新時就只需要加上add[o]就可以了。
1 #include<iostream> 2 #include<string> 3 #include<cstring> 4 #include<cstdio> 5 using namespace std; 6 7 const int maxn = 100000 + 10; 8 int n, m; 9 10 long long add[maxn << 2]; 11 long long sum[maxn << 2]; 12 13 void PushDown(int o, int m) 14 { 15 if (add[o]) 16 { 17 //傳遞懶惰標記 18 add[o << 1] += add[o]; 19 add[o << 1 | 1] += add[o]; 20 //更新子節點的值 21 sum[o << 1] += add[o] * (m - (m >> 1)); 22 sum[o << 1 | 1] += add[o] * (m >> 1); 23 //出去懶惰標記 24 add[o] = 0; 25 } 26 } 27 28 void PushUp(int o) 29 { 30 sum[o] = sum[o << 1] + sum[o << 1 | 1]; 31 } 32 33 void build(int L, int R, int o) 34 { 35 add[o] = 0; 36 if (L == R) 37 { 38 scanf("%lld", &sum[o]); 39 return; 40 } 41 int mid = (L + R) / 2; 42 build(L, mid, 2 * o); 43 build(mid + 1, R, 2 * o + 1); 44 PushUp(o); 45 } 46 47 void update(int L, int R, int x, int l,int r,int o) 48 { 49 if (L <= l && R >= r) //如果找到區間了,則不需要往下更新孩子結點了,等下次需要時再更新 50 { 51 add[o] += x; 52 sum[o] += (r - l + 1)*x; 53 return; 54 } 55 PushDown(o, r - l + 1); 56 int mid = (l + r) / 2; 57 if (L <= mid) 58 update(L, R, x, l, mid, 2 * o); 59 if (R > mid) 60 update(L, R, x, mid + 1, r, 2 * o + 1); 61 PushUp(o); 62 } 63 64 long long query(int L, int R, int l, int r, int o) 65 { 66 if (L <= l && R >= r) 67 return sum[o]; 68 PushDown(o, r - l + 1); 69 int mid = (l + r) / 2; 70 long long ans = 0; 71 if (L <= mid) 72 ans += query(L, R, l, mid, 2 * o); 73 if (R > mid) 74 ans += query(L, R, mid + 1, r, 2 * o + 1); 75 return ans; 76 } 77 78 79 int main() 80 { 81 //freopen("D:\\txt.txt", "r", stdin); 82 while (~scanf("%d%d", &n, &m)) 83 { 84 build(1, n, 1); 85 char c[5]; 86 int x, y, z; 87 while (m--) 88 { 89 scanf("%s", &c); 90 if (c[0] == 'Q') 91 { 92 scanf("%d%d", &x, &y); 93 printf("%lld\n", query(x, y, 1, n, 1)); 94 } 95 else 96 { 97 scanf("%d%d%d", &x, &y, &z); 98 update(x, y, z, 1, n, 1); 99 } 100 } 101 } 102 }?
轉載于:https://www.cnblogs.com/zyb993963526/p/6561795.html
總結
以上是生活随笔為你收集整理的POJ 3468 A Simple Problem with Integers(线段树:区间更新)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Javascript学习之函数(func
- 下一篇: 大一