#include<iostream> #include<sstream> #include<string> #include<vector> #include<list> #include<set> #include<map> #include<stack> #include<queue> #include<algorithm> #include<cmath> #pragma warning(disable:4996) using std::cin; using std::cout; using std::endl; using std::stringstream; using std::string; using std::vector; using std::list; using std::pair; using std::set; using std::multiset; using std::map; using std::multimap; using std::stack; using std::queue; template<typename ElemType> class Interval { public: ElemType first,second,sum,increment; Interval() { first = second = sum = increment = 0; } Interval(const ElemType &f, const ElemType &s) { first = f; second = s; sum = increment = 0; } ElemType mid() { return first + (length() - 1) / 2; } ElemType length() { return second - first + 1; } }; template<typename ElemType> class SegTree { private: vector<Interval<ElemType> >tree; public: SegTree() {} SegTree(const ElemType &n) { tree.resize(4 * n); } void resize(const ElemType &n) { tree.resize(n); } void pushUp(const ElemType &parent)//当前父区间之和为它的两个子区间之和 { tree[parent].sum = tree[parent * 2].sum + tree[parent * 2 + 1].sum; } void pushDown(const ElemType &parent)//把父区间的延时标记下放给两个给两个子区间,然后父区间的延时标记清零 { if (2 * parent < tree.size()) { tree[2 * parent].increment += tree[parent].increment; tree[2 * parent].sum += tree[parent].increment*tree[2 * parent].length(); } if (2 * parent + 1 < tree.size()) { tree[2 * parent + 1].increment += tree[parent].increment; tree[2 * parent + 1].sum += tree[parent].increment*tree[2 * parent + 1].length(); } tree[parent].increment = 0; } //以数组形式建立线段树,当数据离散化之后,调用build(min,max,1) void build(Interval<ElemType>interval, ElemType parent,ElemType &size) { tree[parent] = interval; if (interval.first == interval.second) { cin >> tree[parent].sum; size = std::max(size, parent); return;//当为元线段时停止递归 } ElemType mid = (interval.first + interval.second) / 2; build({ interval.first,mid }, 2 * parent,size); build({ mid + 1,interval.second }, 2 * parent + 1,size); pushUp(parent); } //给闭区间内所有值加上增量increment,返回区间的下标值(如果区间被分割成多块,取下标最大),并且使父区间的sum+=length*increment void insert(Interval<ElemType>interval, ElemType parent, const ElemType &increment) { if (tree[parent].first == interval.first&&interval.second == tree[parent].second) { tree[parent].sum += increment*tree[parent].length(); if (tree[parent].length() == 1) { tree[parent].increment = 0; } else { tree[parent].increment += increment; } return; } pushDown(parent); ElemType mid = tree[parent].mid(); if (interval.second <= mid) { insert(interval, parent * 2, increment); } else if (interval.first > mid) { insert(interval, parent * 2 + 1, increment); } else { insert({ interval.first,mid }, parent * 2, increment); insert({ mid + 1,interval.second }, parent * 2 + 1, increment); } pushUp(parent); } //查询区间之和(假设要求的区间包含于最大区间) ElemType accumulate(pair<ElemType, ElemType>interval, ElemType parent) { //如果要查询的区间==当前区间 if (tree[parent].first == interval.first&&interval.second == tree[parent].second) { //这时候应该从根据该区间的祖先区间的延时标记更新当前区间 return tree[parent].sum; } pushDown(parent); ElemType mid = tree[parent].mid(); if (interval.second <= mid) { return accumulate(interval, parent * 2); } else if (interval.first > mid) { return accumulate(interval, parent * 2 + 1); } return accumulate({ interval.first,mid }, parent * 2) + accumulate({ mid + 1,interval.second }, parent * 2 + 1); } }; int main() { //freopen("input.txt", "r", stdin); //freopen("output.txt","w",stdout); int n, m; while (cin >> n >> m) { SegTree<long long> segtree(n); long long size=0; segtree.build({ 1,n }, 1,size); segtree.resize(size+1); cin.get(); for (int i = 0; i < m; i++) { char order; cin >> order; if (order == 'Q') { long long left, right; cin >> left >> right; cout << segtree.accumulate({ left,right }, 1) << endl; } else { long long left, right, increment; cin >> left >> right >> increment; segtree.insert({ left,right }, 1, increment); } } } return 0; }