题目大意:
题目大意:给定一些数字,有以下几个操作
a、[L,R]区间的数字变化D的数值。并且时间向前推进
b、询问某个时间的[L,R]区间的数字之和,这不花费时间
c、回到X时间。
主席树带动态操作裸题。 但是也可以用主席树,不push版本
AC CODE: 300+M内存使用
#include <bits/stdc++.h>
using namespace std;
#define pr(x) x
#define prln(x) x
//#define pr(x) cout<< #x << " = " <<x<<" "
//#define prln(x) cout<< #x << " = " <<x<<endl
const int maxn = 123456;
const int maxnode = maxn * 100;
int n, m;
struct node
{
int lson, rson;
long long val;//区间权重
long long change;//区间修改值,为0表示没有需要传递的
int ver;
}tree[maxnode];
int tail, root[maxn];
long long w[maxn];
char inp[15];
int ql, qr, qans, qver;
#define LSON tree[o].lson,L, M
#define RSON tree[o].rson, M + 1 , R
#define SELF o,L,R
#define lc tree[o].lson
#define rc tree[o].rson
void push_down(int o, int L, int R)//向下传递标记, o节点的val值不变
{
if (tree[o].change && L < R)
{
if (tree[lc].ver != qver)
{
tree[++tail] = tree[lc];
tree[o].lson = tail;
tree[lc].ver = qver;
}
if (tree[rc].ver != qver)
{
tree[++tail] = tree[rc];
tree[o].rson = tail;
tree[rc].ver = qver;
}
tree[lc].change += tree[o].change;
tree[rc].change += tree[o].change;
tree[o].change = 0;
}
}
//更新o节点的val信息。那么就需要把儿子的信息汇总到o
//要特别注意,儿子的懒人标记的信息和val信息汇总
void maintain(int o, int L, int R)
{
if (L < R)
{
int M = L+(R-L)/2;
tree[o].val = tree[lc].val + tree[rc].val + tree[lc].change * (M-L+1) + tree[rc].change * (R-M);
}
//L==R的情况,不包含的左右儿子,所以再query里询问到的节点,直接结合处理了
}
void build(int o, int L, int R)
{
tree[o].change = 0;
tree[o].ver = 0;//一开始建树,建的是0号版本的
if (L== R)
{
tree[o].val = w[L];
return ;
}
tree[o].lson = ++ tail;
tree[o].rson = ++ tail;
int M = L + (R - L) / 2;
build(LSON);
build(RSON);
maintain(SELF);
}
void insert(int &o, int L, int R)
{
tree[++ tail] = tree[o];
o = tail;
tree[o].ver = qver;
if (ql <= L && R <= qr)
{
tree[o].change += qans;
return;
}
push_down(SELF);
int M = L + (R-L)/2;
if (ql <= M) insert(LSON);
else maintain(LSON);
if (qr > M) insert(RSON);
else maintain(RSON);
maintain(SELF);
}
long long query(int o, int L, int R)
{
if (tree[o].ver != qver)
{
tree[++tail] = tree[o];
o = tail;
tree[o].ver = qver;
}
if (ql <= L && R <= qr)
{
//返回的值需要考虑到懒人标记信息
return tree[o].val + tree[o].change * (R-L+1);//因为根节点的传递标记一直都在
}
push_down(SELF);
int M = L + (R - L) / 2;
long long ret = 0;
if (ql <= M) ret += query(LSON);
else maintain(LSON);
if (qr > M) ret += query(RSON);
else maintain(RSON);
maintain(SELF);
return ret;
}
void init()
{
for (int i = 1; i <=n; ++ i) scanf("%lld", &w[i]);//读入一些数据
root[0] = 0;
tail = 0;
build(root[0], 1, n);
}
void doit()
{
int now =0;
while (m--)
{
scanf("%s", inp);
if (inp[0] == 'C') //区间更新,now+1
{
++now;
root[now] = root[now - 1];
qver = now;
scanf("%d%d%d", &ql, &qr, &qans);//ql,qr区间变化qans
insert(root[now], 1, n);
}
if (inp[0]=='Q') //询问当前
{
scanf("%d%d", &ql, &qr);
qver = now;
printf("%lld\n",query(root[now], 1, n));
}
if (inp[0]=='H') //询问que时间的L,R区间和
{
scanf("%d%d%d", &ql, &qr, &qver);
printf("%lld\n",query(root[qver], 1, n));
}
if (inp[0] == 'B') //回到过去
{
scanf("%d", &now);
}
}
puts("");
}
int main()
{
while (~scanf("%d%d", &n, &m))
{
init();
doit();
}
return 0;
}