SCL -- 线段树
2015-07-15 21:30:57
总结:线段树的题做了这么多,来总结个最典型的区间加法的线段树。
const int MAXN = 100010; int N,Q; int A[MAXN]; struct SMT{ ll tsum[MAXN << 2],add[MAXN << 2],len[MAXN << 2]; void build(int p,int l,int r){ len[p] = r - l + 1; if(l == r){ tsum[p] = A[l]; add[p] = 0; return; } int mid = getmid(l,r); build(p << 1,l,mid); build(p << 1|1,mid + 1,r); push_up(p); } inline void push_up(int p){ tsum[p] = tsum[p << 1] + tsum[p << 1|1]; } inline void push_down(int p){ if(add[p]){ add[p << 1] += add[p]; tsum[p << 1] += add[p] * len[p << 1]; add[p << 1|1] += add[p]; tsum[p << 1|1] += add[p] * len[p << 1|1]; add[p] = 0; } } void update(int a,int b,int c,int p,int l,int r){ if(a <= l && r <= b){ add[p] += c; tsum[p] += c * len[p]; return; } push_down(p); int mid = getmid(l,r); if(a <= mid) update(a,b,c,p << 1,l,mid); if(b > mid) update(a,b,c,p << 1|1,mid + 1,r); push_up(p); } ll query(int a,int b,int p,int l,int r){ if(a <= l && r <= b){ return tsum[p]; } push_down(p); int mid = getmid(l,r); ll res = 0; if(a <= mid) res += query(a,b,p << 1,l,mid); if(b > mid) res += query(a,b,p << 1|1,mid + 1,r); return res; } }smt;