zoukankan      html  css  js  c++  java
  • poj 2104 静态主席树

    我的第一道主席树(静态)。

    先记下自己对主席树的理解:

    主席树的作用是用于查询区间第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
    ", sval[T.query(k,lf,rg)] );
    73     }
    74 }
    View Code
  • 相关阅读:
    iOS获取系统时间
    iOS面试-assign与retain
    iOS-检测网络可连接性
    iOS-ASI异步下载图片
    iOS-NSString值为Unicode格式(字符串编码转换成中文编码)
    iOS-模态视图动画
    iOS-UIScrollView滚动视图(转)
    iOS-NSFileManager
    iOS-self.用法
    iOS-iphone网络编程总结
  • 原文地址:https://www.cnblogs.com/idy002/p/4286999.html
Copyright © 2011-2022 走看看