poj3468(線段樹區間查詢+區間更新)
阿新 • • 發佈:2019-01-05
思路:很明顯的線段樹模板題,區間查詢+區間更新
但是小弟比較菜,並不會線段樹,所以現學了一波,別的還是好理解的,就是lazy標記我覺得很難理解(應該是因為我比較菜),所以請教了大佬,大佬告訴我:lazy標記就是在訪問這個節點時,並且要訪問子節點時,向下傳遞lazy標記,以減少時間;訪問操作包含了(查詢與更新);
程式碼如下:
#include<cstdio> #include<algorithm> using namespace std; /* poj3468 線段樹區間更新,區間查詢 坑點:資料會超過int */ struct SegTree { int l, r;//區間端點 long long val;//區間值 long long lazy;//當訪問到這個節點並且要訪問子節點的時候,向下傳遞標記 //訪問包括了更新跟查詢操作 }segtree[410000]; void pushup(int root)//更新父節點 { segtree[root].val = segtree[root << 1].val + segtree[root << 1 | 1].val; } void pushdown(int root) { segtree[root << 1].lazy += segtree[root].lazy; segtree[root << 1 | 1].lazy += segtree[root].lazy; segtree[root << 1].val += (segtree[root << 1].r - segtree[root << 1].l + 1)*segtree[root].lazy; segtree[root << 1 | 1].val += (segtree[root << 1 | 1].r - segtree[root << 1 | 1].l + 1)*segtree[root].lazy; segtree[root].lazy = 0; } void build(int root, int left, int right) { segtree[root].l = left; segtree[root].r = right; if (left == right) { scanf("%lld", &segtree[root].val); return; } int mid = (left + right) >> 1; build(root << 1, left, mid);//建左子樹 build(root << 1 | 1, mid + 1, right);//建右子樹 pushup(root);//根據左右子樹確定父節點 } long long query(int root, int qleft, int qright) { if (qleft <= segtree[root].l&&qright >= segtree[root].r) { return segtree[root].val; } pushdown(root); long long ans = 0; int mid = (segtree[root].l + segtree[root].r) >> 1; if (qleft <= mid) { ans += query(root << 1, qleft, qright); } if (qright > mid) { ans += query(root << 1 | 1, qleft, qright); } return ans; } void add(int root, int qleft, int qright, long long val) { if (qleft <= segtree[root].l&&qright >= segtree[root].r)//如果當前區間在所求區間中 { segtree[root].val += (segtree[root].r - segtree[root].l + 1)*val; segtree[root].lazy += val; return; } pushdown(root); int mid = (segtree[root].l + segtree[root].r) >> 1; if (qleft <= mid) { add(root << 1, qleft, qright, val); } if (qright > mid) { add(root << 1 | 1, qleft, qright, val); } pushup(root); } int main() { int n, m; char op[10]; scanf("%d%d", &n, &m); build(1, 1, n); while (m--) { scanf("%s", op); if (op[0] == 'Q')//查詢 { int a, b; scanf("%d%d", &a, &b); printf("%lld\n", query(1, a, b)); } else if (op[0] == 'C') { int a, b, val; scanf("%d%d%d", &a, &b, &val); add(1, a, b, val); } } //system("pause"); return 0; } /* 10 1000 1 2 3 4 5 6 7 8 9 10 Q 4 4 Q 1 10 Q 2 4 C 3 6 3 Q 2 4 */