标签:
我的第一道主席树(静态)。
先记下自己对主席树的理解:
主席树的作用是用于查询区间第k大的元素(初始化nlog(n),查询log(n))
主席树=可持续线段树+前缀和思想
主席树实际上是n棵线段树(由于是可持续化线段树,所以实际上是n个长度为log(n)的链),第i棵线段树保存的是a[1]~a[i]这i个数的值域线段树,每个节点维护的是该值域中元素个数,这个是可以相减的,所以建完树后,查询[lf,rg]的第k大时,保存当前查询的值域区间在lf-1和rg这两棵线段树中的节点u,v(不理解看代码),再向下查找时,根据
size[v]-size[u]与k(这里的k是在当前值域的第k大)的大小关系决定向值域的左走还是右走。
(注意空间!)
1 #include <cstdio> 2 #include <algorithm> 3 #define maxn 100010 4 #define maxs 18*maxn 5 using namespace std; 6 7 struct SegTree { 8 int son[maxs][2], siz[maxs], ntot; 9 int root[maxn], vmin, vmax; 10 11 int modify( int v, int nd, int lf, int rg ) { 12 if( lf>=rg ) return 0; 13 int newd = ++ntot; 14 if( lf+1==rg ) { 15 siz[newd] = siz[nd]+1; 16 son[newd][0] = son[newd][1] = 0; 17 return newd; 18 } 19 int mid = (lf+rg)>>1; 20 if( v<mid ) { 21 son[newd][0] = modify( v, son[nd][0], lf, mid ); 22 son[newd][1] = son[nd][1]; 23 } else { 24 son[newd][0] = son[nd][0]; 25 son[newd][1] = modify( v, son[nd][1], mid, rg ); 26 } 27 siz[newd] = siz[son[newd][0]]+siz[son[newd][1]]; 28 return newd; 29 } 30 int query( int k, int u, int v, int lf, int rg ) { 31 int ls = siz[son[v][0]]-siz[son[u][0]]; 32 if( lf+1==rg ) return lf; 33 int mid = (lf+rg)>>1; 34 if( k<=ls ) return query(k,son[u][0],son[v][0],lf,mid); 35 else return query(k-ls,son[u][1],son[v][1],mid,rg); 36 } 37 38 void init( int n ) { 39 ntot = 0; 40 vmin = 1; 41 vmax = n+1; 42 root[0] = 0; 43 } 44 void modify( int pos, int val ) { 45 root[pos] = modify( val, root[pos-1], vmin, vmax ); 46 } 47 int query( int k, int lf, int rg ) { 48 return query( k, root[lf-1], root[rg], vmin, vmax ); 49 } 50 }; 51 52 int n, m; 53 SegTree T; 54 int a[maxn]; 55 int sval[maxn], tot; 56 57 int main() { 58 scanf( "%d%d", &n, &m ); 59 T.init(n); 60 for( int i=1; i<=n; i++ ) { 61 scanf( "%d", a+i ); 62 sval[i] = a[i]; 63 } 64 sort( sval+1, sval+1+n ); 65 tot = unique( sval+1, sval+1+n ) - sval; 66 for( int i=1; i<=n; i++ ) { 67 int dv = lower_bound(sval+1,sval+1+tot,a[i])-sval; 68 T.modify( i, dv ); 69 } 70 for( int i=1,k,lf,rg; i<=m; i++ ) { 71 scanf( "%d%d%d", &lf, &rg, &k ); 72 printf( "%d\n", sval[T.query(k,lf,rg)] ); 73 } 74 }
标签:
原文地址:http://www.cnblogs.com/idy002/p/4286999.html