题意:有一个由n个数组成的序列,有4中操作:
1.C l r d [l,r]这段区间都加上d
2.Q l r 询问[l,r]这段区间的和
3.H l r t 询问之前t时间[l,r]的区间和
4.B t 回到t时间,且下一秒的时间从t开始
按时间建立主席树,主席树上的每一棵线段树维护[1,n]这段序列的信息,这里成段更新的时候要注意,以往写线段树的时候,都是把lazy标记向下传,但是写主席树的时候每一次下传,那么新的节点数就会非常多,会爆内存,所以我们不把lazy操作下传,只是在询问的时候,最后累加的答案加上每一个父亲节点上的lazy值。
1 #include<cstdio>
2 #include<algorithm>
3 #include<queue>
4 #include<iostream>
5 using namespace std;
6 typedef long long ll;
7 const int maxn=1e5+10;
8 ll a[maxn];
9 int root[maxn];
10 struct node
11 {
12 int ln,rn;
13 ll lazy,sum;
14 }tree[maxn*30]; int cnt;
15 void build(int &x,int l,int r)
16 {
17 ++cnt;x=cnt;
18 tree[x].lazy=0;
19 if(l==r){
20 tree[x].sum=a[l];
21 return;
22 }
23 int mid=l+r>>1;
24 build(tree[x].ln,l,mid);
25 build(tree[x].rn,mid+1,r);
26 tree[x].sum=tree[tree[x].ln].sum+tree[tree[x].rn].sum;
27 }
28 void update(int &x,int y,int L,int R,int l,int r,int val)
29 {
30 tree[++cnt]=tree[y];
31 x=cnt;
32 if(L==l&&R==r){
33 tree[cnt].lazy+=val;
34 tree[cnt].sum+=(R-L+1)*val;
35 return;
36 }
37 tree[x].sum+=(R-L+1)*val;
38 int mid=l+r>>1;
39 if(R<=mid) update(tree[x].ln,tree[y].ln,L,R,l,mid,val);
40 else if(L>mid) update(tree[x].rn,tree[y].rn,L,R,mid+1,r,val);
41 else{
42 update(tree[x].ln,tree[y].ln,L,mid,l,mid,val);
43 update(tree[x].rn,tree[y].rn,mid+1,R,mid+1,r,val);
44 }
45 }
46 ll query(int root,int L,int R,int l,int r)
47 {
48 ll ans=0;
49 if(l==L&&r==R) return tree[root].sum;
50 ans+=(ll)tree[root].lazy*(ll)(R-L+1);
51 int mid=l+r>>1;
52 if(R<=mid) ans+=query(tree[root].ln,L,R,l,mid);
53 else if(L>mid) ans+=query(tree[root].rn,L,R,mid+1,r);
54 else{
55 ans+=query(tree[root].ln,L,mid,l,mid);
56 ans+=query(tree[root].rn,mid+1,R,mid+1,r);
57 }
58 return ans;
59 }
60 void init()
61 {
62 cnt=0;
63 }
64 int main()
65 {
66 int n,m;
67 while(scanf("%d%d",&n,&m)!=EOF){
68 init();
69 for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
70 int now=0;
71 build(root[0],1,n);
72 char t1[3];int t2,t3,t4;
73 while(m--){
74 scanf("%s",t1);
75 if(t1[0]=='Q'){
76 //当前时间线;
77 scanf("%d%d",&t2,&t3);
78 ll ans=query(root[now],t2,t3,1,n);
79 printf("%lld\n",ans);
80 }
81 else if(t1[0]=='C'){
82 now++;
83 scanf("%d%d%d",&t2,&t3,&t4);
84 update(root[now],root[now-1],t2,t3,1,n,t4);
85 }
86 else if(t1[0]=='H'){
87 //某个时间线;
88 scanf("%d%d%d",&t2,&t3,&t4);
89 ll ans=query(root[t4],t2,t3,1,n);
90 printf("%lld\n",ans);
91 }
92 else{
93 //返回某个时间线;
94 scanf("%d",&t2);
95 now=t2;
96 }
97 }
98 }
99 return 0;
100 }