標籤:線段樹 演算法 資料結構 poj c++
本文出自blog.csdn.net/svitter
——我大C++的指標豈是爾等能夠簡單領悟!
題意
- 給N個節點,標號A1~An,然後有Q個操作,操作分為Q i j,查詢i,j間的區間和。C i j k,i到j個數字,每個數字增加k,並且輸出。
輸入輸出分析
給N,Q,然後跟操作。注意判斷Q,C使用scanf("%s")。
測試資料:
Sample Input
10 51 2 3 4 5 6 7 8 9 10Q 4 4Q 1 10Q 2 4C 3 6 3Q 2 4
Sample Output
455915
演算法資料結構分析
線段樹基礎題目,但是在其上添加了區間加和操作,增加了難度。 如果每個節點直接更新肯定是不行的,可以儲存sum,inc(增量)來進行計算。 如果區間正好對應,那麼將this.inc += inc。如果區間不是直接對應的,那麼sum值增加inc×增加的個數。 之後在進行查詢的同時,如果inc的值不是0,可以代入到下一層的inc中,本sum += inc×節點個數。
AC代碼:
處理指標的時候出現了些問題,沒有寫L == R的情況溢出。還有就是r <= mid的情況也沒有留意,也造成溢出問題。
最後的問題就是sum一開始忘記inc×個數,直接導致多次WA。
還有就是i從1開始,樹狀數組也是。
//author: svtter//#include <iostream>#include <stdio.h>#include <string.h>#include <vector>#include <map>#include <algorithm>#include <queue>#include <cmath>#define INF 0xffffff#define lln long long#ifdef ONLINE_JUDGE#define FOI(file) 0#define FOW(file) 0#else#define FOI(file) freopen(file,"r",stdin);#define FOW(file) freopen(file,"w",stdout);#endifusing namespace std;struct CNode{ int L, R; CNode *pLeft, *pRight; lln sum; lln inc; int mid() { return (L+R)/2; }};#define N 300000CNode tree[N];int c = 0;void BuildTree(CNode *root, int l, int r){ root->L = l; root->R = r; root->sum = 0; root->inc = 0; //沒寫 if(l == r) return; c ++; root->pLeft = tree+c; c ++; root->pRight = tree+c; if(l != r) { BuildTree(root->pLeft, l, (l+r)/2); BuildTree(root->pRight,(l+r)/2+1, r); }}void Insert(CNode *root, int i, int val){ if(root->L == root->R) { root->sum = val; return; } root->sum += val; if(i <= root->mid()) Insert(root->pLeft, i, val); else Insert(root->pRight, i, val);}void Add(CNode *root, int l, int r, lln inc){ if(root->L == l && root->R == r) { root->inc += inc; return; } root->sum += inc *(r-l+1); if(r <= root->mid()) Add(root->pLeft, l, r, inc); else if(l > root->mid()) Add(root->pRight, l, r, inc); else { Add(root->pLeft, l, root->mid(), inc); Add(root->pRight, root->mid()+1, r, inc); }}lln Query(CNode *root, int l, int r, lln inc){ if(root->L == l && root->R == r) return root->sum + (root->inc+inc) * (r-l+1); if(r <= root->mid()) return Query(root->pLeft, l, r, root->inc+inc); else if(l > root->mid()) return Query(root->pRight,l, r, root->inc+inc); else { return Query(root->pLeft, l, root->mid(), root->inc+inc) + Query(root->pRight, root->mid()+1, r, root->inc+inc); }}int main(){ FOI("input"); //FOW("output"); //write your programme here int n, q, m; int i, j, k; int t; char ch[10]; lln ans; CNode *root; scanf("%d%d", &n ,&q); root = tree; c = 0; BuildTree(root, 1, n); for(i = 1; i <=n ;i++) { scanf("%d", &t); Insert(root, i, t); } for(i = 0; i < q; i++) { scanf("%s", ch); if(ch[0] == 'Q') { scanf("%d%d", &j, &k); ans = Query(root, j, k, 0); printf("%lld\n", ans); } else { scanf("%d%d%d", &j, &k, &m); Add(root, j, k, m); } } return 0;}