题解:因为该题涉及到线段树要还原回去,那么肯定用主席树的区间修改区间查询,我们更新的时候直接将该点的总和加上一个(r-l)*v;
然后查询的时候上面的lazy传递下来,然后再补上(R-L+1)*x,x = 传递下来的lazy总和
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<cstdio>
#include<cmath>
#include<set>
#include<map>
#include<cstdlib>
#include<ctime>
#include<stack>
#include<assert.h>
#include<bitset>
using namespace std;
#define mes(a,b) memset(a,b,sizeof(a))
#define rep(i,a,b) for(int i = a; i <= b; i++)
#define dec(i,a,b) for(int i = b; i >= a; i--)
#define fi first
#define se second
#define ls rt<<1
#define rs rt<<1|1
#define lson ls,L,mid
#define rson rs,mid+1,R
#define lowbit(x) x&(-x)
typedef double db;
typedef long long int ll;
typedef pair<int,int> pii;
typedef unsigned long long ull;
const ll inf = 0x3f3f3f3f;
const int mx = 1e5+5;
const int mod = 1e9+7;
const int x_move[] = {1,-1,0,0,1,1,-1,-1};
const int y_move[] = {0,0,1,-1,1,-1,1,-1};
int n,m;
struct node{
int l,r;
ll sum,lazy;
}T[mx<<6];
int id[mx];
int cnt;
void push_up(int rt){
T[rt].sum = T[T[rt].l].sum+T[T[rt].r].sum;
}
void built(int &rt,int l,int r){
rt = cnt++;
T[rt].lazy = 0;
if(l==r){
scanf("%lld",&T[rt].sum);
return;
}
int mid = l+r>>1;
built(T[rt].l,l,mid);
built(T[rt].r,mid+1,r);
push_up(rt);
}
void update(int pre,int &rt,int L,int R,int l,int r,int c){
rt = cnt++;
T[rt] = T[pre];
T[rt].sum += 1ll*(r-l+1)*c;
if(L>=l&&R<=r){
/// T[rt].sum += 1ll*(R-L+1)*c;
// cout<<T[rt].sum<<endl;
T[rt].lazy += c;
return;
}
int mid = L+R>>1;
if(l>mid) update(T[pre].r,T[rt].r,mid+1,R,l,r,c);
else if(r<=mid) update(T[pre].l,T[rt].l,L,mid,l,r,c);
else{
update(T[pre].l,T[rt].l,L,mid,l,mid,c);
update(T[pre].r,T[rt].r,mid+1,R,mid+1,r,c);
}
}
ll query(int rt,int L,int R,int l,int r,ll x){
if(L>=l&&R<=r){
// cout<<T[rt].sum<<" "<<x<<" "<<R<<endl;
return T[rt].sum+1ll*(R-L+1)*x;
}
int mid = L+R>>1;
if(l>mid) return query(T[rt].r,mid+1,R,l,r,x+T[rt].lazy);
else if(r<=mid) return query(T[rt].l,L,mid,l,r,x+T[rt].lazy);
else return query(T[rt].l,L,mid,l,mid,x+T[rt].lazy)+query(T[rt].r,mid+1,R,mid+1,r,x+T[rt].lazy);
}
int main(){
//freopen("test.in","r",stdin);
//freopen("test.out","w",stdout);
int t,q,ca = 1;
while(scanf("%d%d",&n,&m)!=EOF){
cnt = 1;
q = 0;
built(id[0],1,n);
while(m--){
char op[10];
int l,r,d;
scanf("%s",op);
if(op[0]=='Q'){
scanf("%d%d",&l,&r);
//assert(r>=l);
printf("%lld\n",query(id[q],1,n,l,r,0));
}
else if(op[0]=='H'){
scanf("%d%d%d",&l,&r,&d);
//assert(r>=l);
printf("%lld\n",query(id[d],1,n,l,r,0));
}
else if(op[0]=='B'){
scanf("%d",&d);
q=d;
}
else{
scanf("%d%d%d",&l,&r,&d);
q++;
//assert(r>=l);
update(id[q-1],id[q],1,n,l,r,d);
}
}
}
return 0;
}