推荐几个博客:http://www.cnblogs.com/zyf0163/p/4749042.html 树状结构之主席树
https://blog.csdn.net/creatorx/article/details/75446472 最详细的讲解,让你一次学会主席树
https://blog.csdn.net/jerans/article/details/75807666 主席树题集
https://blog.csdn.net/HTT_H/article/details/47704209 主席树入门专题
https://www.cnblogs.com/RabbitHu/p/segtree.html 递归版主席树
递归版模板大体结构:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 typedef long long ll; 6 const int maxn=5e4+10; 7 const int maxm=2e6+10; 8 int tot; 9 int c[maxm],lson[maxm],rson[maxm]; 10 int T[maxn]; 11 12 void build(int &root,int l,int r) 13 { 14 root=++tot; 15 if ( l==r ) return; 16 int mid=(l+r)/2; 17 build(lson[root],l,mid); 18 build(rson[root],mid+1,r); 19 } 20 21 void update(int root,int &rt,int p,int val,int l,int r) 22 { 23 rt=++tot; 24 lson[rt]=lson[root],rson[rt]=rson[root]; 25 c[rt]=c[root]+val; 26 if ( l==r ) return; 27 int mid=(l+r)/2; 28 if ( p<=mid ) update(lson[rt],lson[rt],p,val,l,mid); 29 else update(rson[rt],rson[rt],p,val,mid+1,r); 30 } 31 32 int query(int rt,int L,int R,int l,int r) 33 { 34 if ( L<=l && r<=R ) return c[rt]; 35 int mid=(l+r)/2; 36 int ans=0; 37 if ( L<=mid ) ans+=query(lson[rt],L,R,l,mid); 38 if ( R>mid ) ans+=query(rson[rt],L,R,mid+1,r); 39 return ans; 40 }
1.(HDOJ2665)http://acm.hdu.edu.cn/showproblem.php?pid=2665
(POJ2104)http://poj.org/problem?id=2104
(POJ2761)http://poj.org/problem?id=2761
题意:求区间第K大,主席树模板题
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<vector> 5 using namespace std; 6 const int maxn=1e5+10; 7 const int maxm=3e6+10; 8 int n,q,m,tot; 9 int a[maxn],t[maxn]; 10 int T[maxn],lson[maxm],rson[maxm],c[maxm]; 11 12 void init_hash() 13 { 14 for ( int i=1;i<=n;i++ ) t[i]=a[i]; 15 sort(t+1,t+1+n); 16 m=unique(t+1,t+1+n)-(t+1); 17 } 18 19 int build(int l,int r) 20 { 21 int root=tot++; 22 c[root]=0; 23 if ( l!=r ) 24 { 25 int mid=(l+r)/2; 26 lson[root]=build(l,mid); 27 rson[root]=build(mid+1,r); 28 } 29 return root; 30 } 31 32 int hash_(int x) 33 { 34 return lower_bound(t+1,t+1+m,x)-t; 35 } 36 37 int update(int root,int pos,int val) 38 { 39 int rt=tot++,tmp=rt; 40 c[rt]=c[root]+val; 41 int l=1,r=m; 42 while ( l<r ) 43 { 44 int mid=(l+r)/2; 45 if ( pos<=mid ) 46 { 47 lson[rt]=tot++;rson[rt]=rson[root]; 48 rt=lson[rt];root=lson[root]; 49 r=mid; 50 } 51 else 52 { 53 rson[rt]=tot++;lson[rt]=lson[root]; 54 rt=rson[rt];root=rson[root]; 55 l=mid+1; 56 } 57 c[rt]=c[root]+val; 58 } 59 return tmp; 60 } 61 62 int query(int lrt,int rrt,int k) 63 { 64 int l=1,r=m; 65 while ( l<r ) 66 { 67 int mid=(l+r)/2; 68 if ( c[lson[rrt]]-c[lson[lrt]]>=k ) 69 { 70 r=mid; 71 lrt=lson[lrt]; 72 rrt=lson[rrt]; 73 } 74 else 75 { 76 l=mid+1; 77 k-=c[lson[rrt]]-c[lson[lrt]]; 78 lrt=rson[lrt]; 79 rrt=rson[rrt]; 80 } 81 } 82 return l; 83 } 84 85 int main() 86 { 87 int Case; 88 scanf("%d",&Case); 89 while ( Case-- ) 90 { 91 scanf("%d%d",&n,&q); 92 tot=0; 93 for ( int i=1;i<=n;i++ ) scanf("%d",&a[i]); 94 init_hash(); 95 T[0]=build(1,m); 96 for ( int i=1;i<=n;i++ ) 97 { 98 int pos=hash_(a[i]); 99 T[i]=update(T[i-1],pos,1); 100 } 101 while ( q-- ) 102 { 103 int l,r,k; 104 scanf("%d%d%d",&l,&r,&k); 105 printf("%d ",t[query(T[l-1],T[r],k)]); 106 } 107 } 108 return 0; 109 }
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 typedef long long ll; 6 const int maxn=1e5+10; 7 const int maxm=3e6+10; 8 int tot,n,q,m; 9 int a[maxn],t[maxn]; 10 int c[maxm],lson[maxm],rson[maxm]; 11 int T[maxn]; 12 13 void init_hash() 14 { 15 for ( int i=1;i<=n;i++ ) t[i]=a[i]; 16 sort(t+1,t+1+n); 17 m=unique(t+1,t+1+n)-(t+1); 18 } 19 20 int hash_(int x) 21 { 22 return lower_bound(t+1,t+1+m,x)-t; 23 } 24 25 void build(int &root,int l,int r) 26 { 27 root=++tot; 28 if ( l==r ) return; 29 int mid=(l+r)/2; 30 build(lson[root],l,mid); 31 build(rson[root],mid+1,r); 32 } 33 34 void update(int root,int &rt,int p,int val,int l,int r) 35 { 36 rt=++tot; 37 lson[rt]=lson[root],rson[rt]=rson[root]; 38 c[rt]=c[root]+val; 39 if ( l==r ) return; 40 int mid=(l+r)/2; 41 if ( p<=mid ) update(lson[rt],lson[rt],p,val,l,mid); 42 else update(rson[rt],rson[rt],p,val,mid+1,r); 43 } 44 45 int query(int rt_,int rt,int l,int r,int k) 46 { 47 if ( l==r ) return l; 48 int mid=(l+r)/2; 49 int sum=c[lson[rt_]]-c[lson[rt]]; 50 if ( sum>=k ) return query(lson[rt_],lson[rt],l,mid,k); 51 else return query(rson[rt_],rson[rt],mid+1,r,k-sum); 52 } 53 54 int main() 55 { 56 int Case; 57 scanf("%d",&Case); 58 while ( Case-- ) 59 { 60 scanf("%d%d",&n,&q); 61 tot=0; 62 for ( int i=1;i<=n;i++ ) scanf("%d",&a[i]); 63 init_hash(); 64 build(T[0],1,m); 65 for ( int i=1;i<=n;i++ ) 66 { 67 int pos=hash_(a[i]); 68 update(T[i-1],T[i],pos,1,1,m); 69 } 70 while ( q-- ) 71 { 72 int l,r,k; 73 scanf("%d%d%d",&l,&r,&k); 74 printf("%d ",t[query(T[r],T[l-1],1,m,k)]); 75 } 76 } 77 return 0; 78 }
2.(HDOJ4417)http://acm.hdu.edu.cn/showproblem.php?pid=4417
题意:求给定区间<=k的数有多少
分析:在模板上将query部分修改一下即可,对于区间[L,R]来说,只需要将第R颗线段树上的[0,k]区间内的值减去第L-1颗线段树上对应区间即可。离线在线都行,离线做法需要将每次访问的k也添加进入hash数组,而对于在线来说转化后的数转化前相对于给定的k来说只能变小不能变大即可
注意:题目给的区间范围从0开始,要将其转化成从1开始
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<vector> 5 using namespace std; 6 const int maxn=1e5+10; 7 const int maxm=3e6+10; 8 int n,q,m,tot; 9 int a[maxn],t[maxn]; 10 int T[maxn],lson[maxm],rson[maxm],c[maxm]; 11 12 void init_hash() 13 { 14 for ( int i=1;i<=n;i++ ) t[i]=a[i]; 15 sort(t+1,t+1+n); 16 m=unique(t+1,t+1+n)-(t+1); 17 } 18 19 int build(int l,int r) 20 { 21 int root=tot++; 22 c[root]=0; 23 if ( l!=r ) 24 { 25 int mid=(l+r)/2; 26 lson[root]=build(l,mid); 27 rson[root]=build(mid+1,r); 28 } 29 return root; 30 } 31 32 int hash_(int x) 33 { 34 return lower_bound(t+1,t+1+m,x)-t; 35 } 36 37 int update(int root,int pos,int val) 38 { 39 int rt=tot++,tmp=rt; 40 c[rt]=c[root]+val; 41 int l=1,r=m; 42 while ( l<r ) 43 { 44 int mid=(l+r)/2; 45 if ( pos<=mid ) 46 { 47 lson[rt]=tot++;rson[rt]=rson[root]; 48 rt=lson[rt];root=lson[root]; 49 r=mid; 50 } 51 else 52 { 53 rson[rt]=tot++;lson[rt]=lson[root]; 54 rt=rson[rt];root=rson[root]; 55 l=mid+1; 56 } 57 c[rt]=c[root]+val; 58 } 59 return tmp; 60 } 61 62 int query(int lrt,int rrt,int k) 63 { 64 int ret=0; 65 int l=1,r=m; 66 while ( l<r ) 67 { 68 int mid=(l+r)/2; 69 if ( k<=mid ) 70 { 71 r=mid; 72 lrt=lson[lrt]; 73 rrt=lson[rrt]; 74 } 75 else 76 { 77 ret+=c[lson[rrt]]-c[lson[lrt]]; 78 l=mid+1; 79 lrt=rson[lrt]; 80 rrt=rson[rrt]; 81 } 82 } 83 ret+=c[rrt]-c[lrt]; 84 return ret; 85 } 86 87 int main() 88 { 89 int Case,h; 90 scanf("%d",&Case); 91 for ( h=1;h<=Case;h++ ) 92 { 93 scanf("%d%d",&n,&q); 94 tot=0; 95 for ( int i=1;i<=n;i++ ) 96 { 97 scanf("%d",&a[i]); 98 a[i]++; 99 } 100 init_hash(); 101 T[0]=build(1,m); 102 for ( int i=1;i<=n;i++ ) 103 { 104 int pos=hash_(a[i]); 105 T[i]=update(T[i-1],pos,1); 106 } 107 printf("Case %d: ",h); 108 while ( q-- ) 109 { 110 int l,r,k,p; 111 scanf("%d%d%d",&l,&r,&k); 112 l++,r++,k++; 113 p=hash_(k); 114 if ( t[p]>k ) p--; 115 if ( p==0 ) printf("0 "); 116 else printf("%d ",query(T[l-1],T[r],p)); 117 } 118 } 119 return 0; 120 }
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<vector> 5 using namespace std; 6 const int maxn=1e5+10; 7 const int maxm=3e6+10; 8 int n,q,m,tot; 9 int a[maxn],t[maxn*2],l[maxn],r[maxn],val[maxn]; 10 int T[maxn],lson[maxm],rson[maxm],c[maxm]; 11 12 void init_hash() 13 { 14 for ( int i=1;i<=n;i++ ) t[i]=a[i]; 15 for ( int i=1;i<=q;i++ ) t[i+n]=val[i]; 16 sort(t+1,t+1+n+q); 17 m=unique(t+1,t+1+n+q)-(t+1); 18 } 19 20 int build(int l,int r) 21 { 22 int root=tot++; 23 c[root]=0; 24 if ( l!=r ) 25 { 26 int mid=(l+r)/2; 27 lson[root]=build(l,mid); 28 rson[root]=build(mid+1,r); 29 } 30 return root; 31 } 32 33 int hash_(int x) 34 { 35 return lower_bound(t+1,t+1+m,x)-t; 36 } 37 38 int update(int root,int pos,int val) 39 { 40 int rt=tot++,tmp=rt; 41 c[rt]=c[root]+val; 42 int l=1,r=m; 43 while ( l<r ) 44 { 45 int mid=(l+r)/2; 46 if ( pos<=mid ) 47 { 48 lson[rt]=tot++;rson[rt]=rson[root]; 49 rt=lson[rt];root=lson[root]; 50 r=mid; 51 } 52 else 53 { 54 rson[rt]=tot++;lson[rt]=lson[root]; 55 rt=rson[rt];root=rson[root]; 56 l=mid+1; 57 } 58 c[rt]=c[root]+val; 59 } 60 return tmp; 61 } 62 63 int query(int lrt,int rrt,int k) 64 { 65 int ret=0; 66 int l=1,r=m; 67 while ( l<r ) 68 { 69 int mid=(l+r)/2; 70 if ( k<=mid ) 71 { 72 r=mid; 73 lrt=lson[lrt]; 74 rrt=lson[rrt]; 75 } 76 else 77 { 78 ret+=c[lson[rrt]]-c[lson[lrt]]; 79 l=mid+1; 80 lrt=rson[lrt]; 81 rrt=rson[rrt]; 82 } 83 } 84 ret+=c[rrt]-c[lrt]; 85 return ret; 86 } 87 88 int main() 89 { 90 int Case,h; 91 scanf("%d",&Case); 92 for ( h=1;h<=Case;h++ ) 93 { 94 scanf("%d%d",&n,&q); 95 tot=0; 96 for ( int i=1;i<=n;i++ ) 97 { 98 scanf("%d",&a[i]); 99 a[i]++; 100 } 101 for ( int i=1;i<=q;i++ ) { 102 scanf("%d%d%d",&l[i],&r[i],&val[i]); 103 l[i]++,r[i]++,val[i]++; 104 } 105 init_hash(); 106 T[0]=build(1,m); 107 for ( int i=1;i<=n;i++ ) 108 { 109 int pos=hash_(a[i]); 110 T[i]=update(T[i-1],pos,1); 111 } 112 printf("Case %d: ",h); 113 for ( int i=1;i<=q;i++ ) 114 { 115 int L,R,k; 116 L=l[i],R=r[i],k=val[i]; 117 k=hash_(k); 118 printf("%d ",query(T[L-1],T[R],k)); 119 } 120 } 121 return 0; 122 }
3.(SPOJ3267)http://www.spoj.com/problems/DQUERY/
题意:给出一个长度为n 的数列,有q 个询问,每个询问给出数对 [i,j],需要你给出这一段中有多少不同的数字
分析:利用map记录每个数的位置,主席树建新树的时候,如果当前元素出现过,那么把这个元素上次出现的位置减一,然后当前位置加一,如果没出现过就是普通的建树操作。
对于查询[l, r]我们只需要取出第r棵树,然后输出这棵树[l,r]之间的和,因为是按从1到n的顺序插入的,所以每次只需要求>=l的个数即可。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<vector> 5 #include<map> 6 using namespace std; 7 const int maxn=3e4+10; 8 const int maxm=3e6+10; 9 int n,q,tot; 10 int a[maxn]; 11 int T[maxn],lson[maxm],rson[maxm],c[maxm]; 12 13 int build(int l,int r) 14 { 15 int root=tot++; 16 c[root]=0; 17 if ( l!=r ) 18 { 19 int mid=(l+r)/2; 20 lson[root]=build(l,mid); 21 rson[root]=build(mid+1,r); 22 } 23 return root; 24 } 25 26 int update(int root,int pos,int val) 27 { 28 int rt=tot++,tmp=rt; 29 c[rt]=c[root]+val; 30 int l=1,r=n; 31 while ( l<r ) 32 { 33 int mid=(l+r)/2; 34 if ( pos<=mid ) 35 { 36 lson[rt]=tot++;rson[rt]=rson[root]; 37 rt=lson[rt];root=lson[root]; 38 r=mid; 39 } 40 else 41 { 42 rson[rt]=tot++;lson[rt]=lson[root]; 43 rt=rson[rt];root=rson[root]; 44 l=mid+1; 45 } 46 c[rt]=c[root]+val; 47 } 48 return tmp; 49 } 50 51 int query(int rt,int lpos) 52 { 53 int ret=0; 54 int l=1,r=n; 55 while ( lpos>l ) 56 { 57 int mid=(l+r)/2; 58 if ( lpos<=mid ) 59 { 60 r=mid; 61 ret+=c[rson[rt]]; 62 rt=lson[rt]; 63 } 64 else 65 { 66 rt=rson[rt]; 67 l=mid+1; 68 } 69 } 70 return ret+c[rt]; 71 } 72 73 int main() 74 { 75 int Case; 76 while ( scanf("%d",&n)!=EOF ) 77 { 78 tot=0; 79 for ( int i=1;i<=n;i++ ) scanf("%d",&a[i]); 80 T[0]=build(1,n); 81 map<int,int>mp; 82 for ( int i=1;i<=n;i++ ) 83 { 84 if ( mp.find(a[i])!=mp.end() ) 85 { 86 int tmp=update(T[i-1],mp[a[i]],-1); 87 T[i]=update(tmp,i,1); 88 } 89 else T[i]=update(T[i-1],i,1); 90 mp[a[i]]=i; 91 } 92 scanf("%d",&q); 93 while ( q-- ) 94 { 95 int l,r; 96 scanf("%d%d",&l,&r); 97 printf("%d ",query(T[r],l)); 98 } 99 } 100 return 0; 101 }
4.(ZOJ2112)http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2112
题意:给定一串序列,有两种操作,一种是求区间[l,r]第k大,另外一种是将a[i]=t
带修改的主席树,推荐几个博客:http://www.cnblogs.com/Empress/p/4659824.html
https://blog.csdn.net/acm_cxlove/article/details/8565309
http://www.cnblogs.com/Rlemon/archive/2013/05/24/3096264.html
模板来自kuangbin:http://www.cnblogs.com/kuangbin/p/3308118.html
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<vector> 5 using namespace std; 6 const int maxn=60010; 7 const int maxm=2500010; 8 int n,q,m,tot; 9 int a[maxn],t[maxn]; 10 int T[maxn],lson[maxm],rson[maxm],c[maxm]; 11 int S[maxn]; 12 struct Query{ 13 int kind; 14 int l,r,k; 15 }query[10010]; 16 17 void init_hash(int k) 18 { 19 sort(t+1,t+k+1); 20 m=unique(t+1,t+k+1)-(t+1); 21 } 22 23 int hash_(int x) 24 { 25 return lower_bound(t+1,t+m+1,x)-t; 26 } 27 28 int build(int l,int r) 29 { 30 int root=tot++; 31 c[root]=0; 32 if ( l!=r ) 33 { 34 int mid=(l+r)/2; 35 lson[root]=build(l,mid); 36 rson[root]=build(mid+1,r); 37 } 38 return root; 39 } 40 41 int update(int root,int pos,int val) 42 { 43 int rt=tot++,tmp=rt; 44 c[rt]=c[root]+val; 45 int l=1,r=m; 46 while ( l<r ) 47 { 48 int mid=(l+r)/2; 49 if ( pos<=mid ) 50 { 51 lson[rt]=tot++;rson[rt]=rson[root]; 52 rt=lson[rt];root=lson[root]; 53 r=mid; 54 } 55 else 56 { 57 rson[rt]=tot++;lson[rt]=lson[root]; 58 rt=rson[rt];root=rson[root]; 59 l=mid+1; 60 } 61 c[rt]=c[root]+val; 62 } 63 return tmp; 64 } 65 66 int lowbit(int x) 67 { 68 return x&(-x); 69 } 70 71 int used[maxn]; 72 void add(int x,int pos,int val) 73 { 74 while ( x<=n ) 75 { 76 S[x]=update(S[x],pos,val); 77 x+=lowbit(x); 78 } 79 } 80 81 int sum(int x) 82 { 83 int ret=0; 84 while ( x>0 ) 85 { 86 ret+=c[lson[used[x]]]; 87 x-=lowbit(x); 88 } 89 return ret; 90 } 91 92 int Q(int left,int right,int k) 93 { 94 int lrt=T[left]; 95 int rrt=T[right]; 96 int l=1,r=m; 97 for ( int i=left;i>0;i-=lowbit(i)) used[i]=S[i]; 98 for ( int i=right;i>0;i-=lowbit(i)) used[i]=S[i]; 99 while ( l<r ) 100 { 101 int mid=(l+r)/2; 102 int tmp=sum(right)-sum(left)+c[lson[rrt]]-c[lson[lrt]]; 103 if ( tmp>=k ) 104 { 105 r=mid; 106 for ( int i=left;i>0;i-=lowbit(i)) used[i]=lson[used[i]]; 107 for ( int i=right;i>0;i-=lowbit(i)) used[i]=lson[used[i]]; 108 lrt=lson[lrt]; 109 rrt=lson[rrt]; 110 } 111 else 112 { 113 l=mid+1; 114 k-=tmp; 115 for ( int i=left;i>0;i-=lowbit(i)) used[i]=rson[used[i]]; 116 for ( int i=right;i>0;i-=lowbit(i)) used[i]=rson[used[i]]; 117 lrt=rson[lrt]; 118 rrt=rson[rrt]; 119 } 120 } 121 return l; 122 } 123 124 int main() 125 { 126 int Case; 127 scanf("%d",&Case); 128 while ( Case-- ) 129 { 130 scanf("%d%d",&n,&q); 131 tot=0; 132 m=0; 133 for ( int i=1;i<=n;i++ ) 134 { 135 scanf("%d",&a[i]); 136 t[++m]=a[i]; 137 } 138 char op[10]; 139 for ( int i=0;i<q;i++ ) 140 { 141 scanf("%s",op); 142 if ( op[0]=='Q' ) 143 { 144 query[i].kind=0; 145 scanf("%d%d%d",&query[i].l,&query[i].r,&query[i].k); 146 } 147 else 148 { 149 query[i].kind=1; 150 scanf("%d%d",&query[i].l,&query[i].r); 151 t[++m]=query[i].r; 152 } 153 } 154 init_hash(m); 155 T[0]=build(1,m); 156 for ( int i=1;i<=n;i++ ) 157 { 158 int pos=hash_(a[i]); 159 T[i]=update(T[i-1],pos,1); 160 } 161 for ( int i=1;i<=n;i++ ) S[i]=T[0]; 162 for ( int i=0;i<q;i++ ) 163 { 164 if ( query[i].kind==0 ) printf("%d ",t[Q(query[i].l-1,query[i].r,query[i].k)]); 165 else 166 { 167 add(query[i].l,hash_(a[query[i].l]),-1); 168 add(query[i].l,hash_(query[i].r),1); 169 a[query[i].l]=query[i].r; 170 } 171 } 172 } 173 return 0; 174 }
5.(HDOJ4348)http://acm.hdu.edu.cn/showproblem.php?pid=4348
题意:给出一段长度为n的序列,有4种操作。初始时,时间戳=0
a.C l r d [l,r]区间内的数+d,时间戳++
b.Q l r 求当前时间戳下[l,r]区间的和
c.H l r t 求时间戳=t下[l,r]区间的和
d.B t 时间戳=t
分析:推荐两个讲解较为详细的博客https://blog.csdn.net/glqac/article/details/45103859
https://blog.csdn.net/kirito16/article/details/47266801
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<vector> 5 using namespace std; 6 typedef long long ll; 7 const int maxn=1e5+10; 8 const int maxm=3e6+10; 9 int n,q,tot; 10 int a[maxn]; 11 int T[maxn],lson[maxm],rson[maxm]; 12 ll sum[maxm],add[maxm]; 13 14 int build(int l,int r) 15 { 16 int root=tot++; 17 add[root]=0; 18 if ( l!=r ) 19 { 20 int mid=(l+r)/2; 21 lson[root]=build(l,mid); 22 rson[root]=build(mid+1,r); 23 } 24 else 25 { 26 scanf("%lld",&sum[root]); 27 return root; 28 } 29 sum[root]=sum[lson[root]]+sum[rson[root]]; 30 return root; 31 } 32 33 34 void pushup(int rt,int len) 35 { 36 sum[rt]=sum[lson[rt]]+sum[rson[rt]]+add[lson[rt]]*(len-len/2)+add[rson[rt]]*(len/2); 37 } 38 39 int A,B; 40 ll val; 41 42 int update(int root,int l,int r) 43 { 44 int rt=tot++; 45 add[rt]=add[root]; 46 if ( A<=l && r<=B ) 47 { 48 sum[rt]=sum[root]; 49 add[rt]=add[root]+val; 50 lson[rt]=lson[root]; 51 rson[rt]=rson[root]; 52 return rt; 53 } 54 int mid=(l+r)/2; 55 if ( A<=mid ) lson[rt]=update(lson[root],l,mid); 56 else lson[rt]=lson[root]; 57 if ( B>mid ) rson[rt]=update(rson[root],mid+1,r); 58 else rson[rt]=rson[root]; 59 pushup(rt,r-l+1); 60 return rt; 61 } 62 63 ll query(int root,int l,int r,ll add_) 64 { 65 if ( A<=l && r<=B ) return sum[root]+(add_+add[root])*(r-l+1); 66 ll ans=0; 67 int mid=(l+r)/2; 68 if ( A<=mid ) ans+=query(lson[root],l,mid,add[root]+add_); 69 if ( B>mid ) ans+=query(rson[root],mid+1,r,add[root]+add_); 70 return ans; 71 } 72 73 int main() 74 { 75 char op[5]; 76 int now,Case=0; 77 while ( scanf("%d%d",&n,&q)!=EOF ) 78 { 79 if ( Case!=0 ) printf(" "); 80 Case++; 81 tot=0; 82 T[0]=build(1,n); 83 now=0; 84 while ( q-- ) 85 { 86 ll ans; 87 int k; 88 scanf("%s",op); 89 if ( op[0]=='C' ) 90 { 91 scanf("%d%d%lld",&A,&B,&val); 92 T[now+1]=update(T[now],1,n); 93 now++; 94 } 95 else if ( op[0]=='Q' ) 96 { 97 scanf("%d%d",&A,&B); 98 ans=query(T[now],1,n,0); 99 printf("%lld ",ans); 100 } 101 else if ( op[0]=='H' ) 102 { 103 scanf("%d%d%d",&A,&B,&k); 104 ans=query(T[k],1,n,0); 105 printf("%lld ",ans); 106 } 107 else if ( op[0]=='B' ) 108 { 109 scanf("%d",&k); 110 now=k; 111 tot=T[now+1]; 112 } 113 } 114 } 115 return 0; 116 }