码迷,mamicode.com
首页 > 其他好文 > 详细

主席树 | | 可持久化线段树

时间:2014-08-20 16:05:12      阅读:205      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   os   io   数据   for   

可持久化数据结构(Persistent data structure)就是利用函数式编程的思想使其支持询问历史版本、同时充分利用它们之间的共同数据来减少时间和空间消耗。

所以这里讲的可持久化线段树也叫函数式线段树(又叫主席树……因为先驱就是fotile主席Orz……)。

先了解一下主席树

http://seter.is-programmer.com/posts/31907.html     很详细的介绍了函数式线段树(主席树)。

主席树其实就是很多棵线段树,由于每次更新只需要更新logN个节点,所以主席树的内存不用到达N*N的级别,只需要NlogN级别。。

每次更新的时候都新建一个节点,然后递归下去,更新了logN个节点,其他的节点就与之前建的线段树一起共用。。

http://acm.hdu.edu.cn/showproblem.php?pid=4417 hdu4417 Super Mario

题意:给定一段区间每个点有个高度。在m次询问中每次给出左右端点和可以到达的高度,统计有多少个是小于到达高度

做法:主席树 + 离散化。。输入比较大,所以需要离散化。。tot统计总的节点个数,结构体的sum是统计出现的数的个数,每次询问[l, r] x的时候,就在第r棵线段树-第l-1棵线段树( 相当于[l, r]区间的数 ) 里面找小于等于x的个数。。建议先看代码,看不懂再去在主席树的介绍,这样重复的看。。

bubuko.com,布布扣
 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<string>
 5 #include<algorithm>
 6 #include<queue>
 7 #include<cmath>
 8 #include<vector>
 9 
10 using namespace std;
11 
12 #define mnx 100050
13 #define ll long long
14 #define mod 1000000007
15 #define inf 223372036854775807
16 #define eps 1e-10
17 #define Pi acos(-1.0);
18 #define lson l, m, rt << 1
19 #define rson m+1, r, rt << 1 | 1
20 
21 ll a[mnx], b[mnx];
22 int root[mnx], tot;
23 struct node{
24     int ls, rs, sum;
25 }p[mnx*20];
26 int build( int l, int r ){
27     int rt = tot++;
28     p[rt].sum = 0;
29     if( l == r ) return rt;
30     int m = ( l + r ) >> 1;
31     p[rt].ls = build( l, m );
32     p[rt].rs = build( m + 1, r );
33     return rt;
34 }
35 int update( int x, int v, int i, int l, int r ){
36     int rt = tot++;
37     p[rt] = p[i];
38     p[rt].sum += v;
39     if( l == r ) return rt;
40     int m = ( l + r ) >> 1;
41     if( x <= m ) p[rt].ls = update( x, v, p[i].ls, l, m );
42     else p[rt].rs = update( x, v, p[i].rs, m + 1, r );
43     return rt;
44 }
45 int query( int i, int j, int k, int l, int r ){
46     if( l == r ) return p[i].sum - p[j].sum;
47     int ret = 0, m = ( l + r ) >> 1;
48     if( k > m ){
49         ret += ( p[p[i].ls].sum - p[p[j].ls].sum );
50         ret += query( p[i].rs, p[j].rs, k, m + 1, r );
51     }
52     else{
53         ret += query( p[i].ls, p[j].ls, k, l, m );
54     }
55     return ret;
56 }
57 int main(){
58     int cas, cnt = 1;
59     scanf( "%d", &cas );
60     while( cas-- ){
61         tot = 0;
62         int n, m;
63         scanf( "%d %d", &n, &m );
64         for( int i = 1; i <= n; i++ ){
65             scanf( "%I64d", &a[i] );
66             b[i] = a[i];
67         }
68         sort( b + 1, b + 1 + n );
69         int tmp = unique( b + 1, b + 1 + n ) - b - 1;
70         tmp++, b[tmp] = inf;
71         root[0] = build( 1, tmp );
72         for( int i = 1; i <= n; i++ ){
73             int k = lower_bound( b + 1, b + 1 + tmp, a[i] ) - b;
74             root[i] = update( k, 1, root[i-1], 1, tmp ); 
75         }
76         printf( "Case %d:\n", cnt++ );
77         while( m-- ){
78             int l, r; ll v;
79             scanf( "%d %d %I64d", &l, &r, &v );
80             l++, r++;
81             int k = upper_bound( b + 1, b + 1 + tmp, v ) - b - 1;
82             int ans = 0;
83             if( k > 0 ) ans = query( root[r], root[l-1], k, 1, tmp );
84             printf( "%d\n", ans );
85         }
86     }
87     return 0;
88 }
View Code

 

主席树 | | 可持久化线段树,布布扣,bubuko.com

主席树 | | 可持久化线段树

标签:style   blog   http   color   os   io   数据   for   

原文地址:http://www.cnblogs.com/LJ-blog/p/3924737.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!