PKU 3468 线段树

来源:互联网 发布:response.json 编辑:程序博客网 时间:2024/05/21 22:25
/****************************************************************************************************    从NotOnlySuccess的blog上开始重学线段树。。。这个是线段树中延迟标记的运用~****************************************************************************************************/#include <iostream>#include <functional>#include <algorithm>#include <complex>#include <cstdlib>#include <cstring>#include <fstream>#include <sstream>#include <utility>#include <bitset>#include <cctype>#include <cstdio>#include <limits>#include <memory>#include <string>#include <vector>#include <cmath>#include <ctime>#include <queue>#include <stack>#include <list>#include <map>#include <set>using namespace std;#define LOWBIT(x) ( (x) & ( (x) ^ ( (x) - 1 ) ) )#define CLR(x, k) memset((x), (k), sizeof(x))#define CPY(t, s) memcpy((t), (s), sizeof(s))#define SC(t, s) static_cast<t>(s)#define LEN(s) static_cast<int>( strlen((s)) )#define SZ(s) static_cast<int>( (s).size() )typedef double LF;//typedef long long LL;//GNU C++//typedef unsigned long long ULL;typedef __int64 LL;//Visual C++ 2010typedef unsigned __int64 ULL;typedef pair<int, int> PII;typedef pair<LL, LL> PLL;typedef pair<double, double> PDD;typedef map<int, int>::iterator MI;typedef vector<int>::iterator VI;typedef list<int>::iterator LI;typedef set<int>::iterator SI;template <typename T>T sqa(const T &x){return x * x;}template <typename T>T gcd(T a, T b){if (!a || !b){return max(a, b);}T t;while (t = a % b){a = b;b = t;}return b;}template <typename T>T ext_gcd(T a, T b, T &x, T &y){if (!b){x = 1;y = 0;return a;}T d = ext_gcd(b, a % b, x, y);T t = x;x = y;y = t - a / b * y;return d;}template <typename T>T invmod(T a, T p){LL inv, y;ext_gcd(a, p, inv, y);inv < 0 ? inv += p : 0; return inv;}const int INF_INT = 0x3f3f3f3f;const LL INF_LL = 0x7fffffffffffffffLL;//15fconst double oo = 10e9;const double eps = 10e-7;const double PI = acos(-1.0);const int MAXN = 100004 << 2;int n, m, arr[MAXN];struct Node{int left, right;int add;LL sum;Node(){memset(this, 0, sizeof(this));}int dis(){return right - left + 1;}}st[MAXN];int inline ll(const int &x){return x << 1;}int inline rr(const int &x){return x << 1 | 1;}void initST(){memset(st, 0, sizeof(st));return ;}void buildST(int l, int r, int t){st[t].left = l;st[t].right = r;st[t].add = 0;if (l == r){st[t].sum = arr[l];return ;}int mid = (l + r) >> 1;buildST(l, mid, ll(t));buildST(mid + 1, r, rr(t));st[t].sum = st[ ll(t) ].sum + st[ rr(t) ].sum;return ;}void updateST(int l, int r, int inc, int t){if (l <= st[t].left && st[t].right <= r){st[t].add += inc;st[t].sum += SC(LL, inc) * st[t].dis();return ;}if (st[t].add)//add实际上是延迟标记{st[ ll(t) ].add += st[t].add;//把延迟标记推向左子树st[ rr(t) ].add += st[t].add;//把延迟标记推向右子树st[ ll(t) ].sum += SC(LL, st[t].add) * st[ ll(t) ].dis();//同时左右子树的sum值也被更新st[ rr(t) ].sum += SC(LL, st[t].add) * st[ rr(t) ].dis();st[t].add = 0;}int mid = st[ ll(t) ].right;if (r <= mid){updateST(l, r, inc, ll(t));}else if (l > mid){updateST(l, r, inc, rr(t));}else{updateST(l, mid, inc, ll(t));updateST(mid + 1, r, inc, rr(t));}st[t].sum = st[ ll(t) ].sum + st[ rr(t) ].sum;return ;}LL query(int l, int r, int t){if (l <= st[t].left && st[t].right <= r){return st[t].sum;}if (st[t].add){st[ ll(t) ].sum += SC(LL, st[t].add) * st[ ll(t) ].dis();st[ rr(t) ].sum += SC(LL, st[t].add) * st[ rr(t) ].dis();st[ ll(t) ].add += st[t].add;st[ rr(t) ].add += st[t].add;st[t].add = 0;}int mid = st[ ll(t) ].right;if (r <= mid){return query(l, r, ll(t));}else if (l > mid){return query(l, r, rr(t));}return query(l, mid, ll(t)) + query(mid + 1, r, rr(t));}void ace(){char op[2];int l, r, inc;while (scanf("%d %d", &n, &m) != EOF){for (int i = 1; i <= n; ++i){scanf("%d", arr + i);}initST();buildST(1, n, 1);while (m--){scanf("%s %d %d", op, &l, &r);if (l > r){swap(l, r);}if ('Q' == op[0]){cout << query(l, r, 1) << endl;}else{scanf("%d", &inc);updateST(l, r, inc, 1);}}}return ;}int main(){ace();return 0;}