法一:暴力!
让干什么就干什么,那么久需要可持久化线段树了。
但是空间好紧。怎么破?
不down标记好了!
每个点维护sum和add两个信息,sum是这段真实的和,add是这段整体加了多少,如果这段区间被完全包含,返回sum,否则加上add * 询问落在这段区间的长度再递归回答。
怎么还是MLE?
麻辣鸡指针好像8字节,所以改成数组的就过了。。。
#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<iostream> using namespace std; template<typename Q> Q &read(Q &x) { static char c, f; for(f = 0; c = getchar(), !isdigit(c); ) if(c == '-') f = 1; for(x = 0; isdigit(c); c = getchar()) x = x * 10 + c - '0'; if(f) x = -x; return x; } template<typename Q> Q read() { static Q x; read(x); return x; } typedef long long LL; const int N = 100000 + 10; struct Node *pis; struct Node { LL sum, add; Node *ch[2]; Node *modify(int l, int r, int L, int R, LL d) { Node *o = new Node(*this); if(L <= l && r <= R) { o->add += d; o->sum += (r - l + 1) * d; return o; } int mid = (l + r) >> 1; if(L <= mid) o->ch[0] = ch[0]->modify(l, mid, L, R, d); if(mid < R) o->ch[1] = ch[1]->modify(mid + 1, r, L, R, d); o->sum = o->ch[0]->sum + o->ch[1]->sum + o->add * (r - l + 1); return o; } LL query(int l, int r, int L, int R) { if(L <= l && r <= R) return sum; int mid = (l + r) >> 1; LL res = (min(R, r) - max(L, l) + 1) * add; if(L <= mid) res += ch[0]->query(l, mid, L, R); if(mid < R) res += ch[1]->query(mid + 1, r, L, R); return res; } void *operator new(size_t) { return pis++; } }pool[1000000 + 10], *root[N]; void build(Node *&o, int l, int r) { o = new Node, o->add = 0; if(l == r) return read(o->sum), void(); int mid = (l + r) >> 1; build(o->ch[0], l, mid); build(o->ch[1], mid + 1, r); o->sum = o->ch[0]->sum + o->ch[1]->sum; } int main() { #ifdef DEBUG freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout); #endif int n, m, cur; char opt[10]; while(scanf("%d%d", &n, &m) == 2) { cur = 0, pis = pool; build(root[cur], 1, n); while(m--) { if(m == 1) { int debug = 1; } scanf("%s", opt); if(opt[0] == 'C') { int l, r; LL d; read(l), read(r), read(d); root[cur + 1] = root[cur]->modify(1, n, l, r, d); cur++; }else if(opt[0] == 'Q') { int l, r; read(l), read(r); printf("%I64d\n", root[cur]->query(1, n, l, r)); }else if(opt[0] == 'H') { int l, r, t; read(l), read(r), read(t); printf("%I64d\n", root[t]->query(1, n, l, r)); }else read(cur); } puts(""); } return 0; }