专题训练之主席树

推荐几个博客: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 }
HDOJ2665
 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 }
HDOJ2665(递归版)

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 }
HDOJ4417(在线)
  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 }
HDOJ4417(离线)

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 }
SPOJ3267

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 }
ZOJ2112

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 }
HDOJ4348
原文地址:https://www.cnblogs.com/HDUjackyan/p/9069311.html