[POJ2104] 主席树模板题

来源:互联网 发布:windows优化大师电脑版 编辑:程序博客网 时间:2024/05/16 14:42

第一次写主席树,比较畏惧,害怕又会因为一些小错误调试半天,就拿这玩意当模板题写了,然而并没有想象的困难。


抱怨几句

指针的写法要判NULL真的麻烦= =
随便写什么树一眼望过去全是

if(XXXX!=NULL)

关于题目

题目连接:POJ2104
题目大意:给你一串数字,每次询问区间[L,R]的第K大


分析与思路

感觉没有什么可以说的····
就是要注意建树的时候,后一个节点相对于前一个节点的树实际上只改动了一条链,或者说只有一条链与前一棵树不同。

如果元素要进左子树的话,右子树就会跟上个树这个区间的右子树是完全一样的,因此,可以直接将本树本节点的右子树指针接到上棵树当前节点的右儿子,这样即省时间,又省空间。
from Oyking cnblogs
细节看代码。


代码

Problem: 2104       User: NafarioMemory: 49140K      Time: 2469MSLanguage: C++       Result: Accepted#include<algorithm> #include<cstring>#include<cstdio>#include<iostream>using namespace std;int N , M ;struct node{    int siz ;    node *ls , *rs ;    node(){        ls = rs = NULL ;        siz = 0 ;    }    void update(){        siz = 0 ;        if(ls) siz += ls->siz ;        if(rs) siz += rs->siz ;    }}w[200005 * 20] , *tw = w , *root[200005] ;int ori[200005] , ns[200005] , arcns[200005] , so[200005] , siz ;void read_uniq(){    for( int i = 1 ; i <= N ; i ++ ){        scanf( "%d" , &ori[i] ) ;         so[i] = ns[i] = ori[i] ;    }    sort ( so + 1 , so + N + 1 ) ;    siz = unique( so + 1 , so + N + 1 ) - so - 1 ;    for( int i = 1 ; i <= N ; i ++ ){        ns[i] = lower_bound( so + 1 , so + siz + 1 , ns[i] ) - so  ;        arcns[ ns[i] ] = ori[i] ;    }}void Insert( node *&las , node *&nd , int lf , int rg , int val ) {    nd = ++tw ;    las = ( las == NULL  ?  &w[0] : las ) ;    *nd = node();    //printf( "nd = %d  lf = %d rg = %d val = %d\n" ,nd , lf , rg , val ) ;    int mid = ( lf + rg ) >> 1 ;    if( lf == rg ){        *nd = *las ;        nd->siz ++ ;        return ;    } else if( val <= mid ){        Insert( las->ls , nd->ls , lf , mid , val ) ;        nd->rs = las->rs ;    } else {        Insert( las->rs , nd->rs , mid + 1 , rg , val ) ;        nd->ls = las->ls ;    }    nd->update() ;}int Query( node* &Lnd , node* &Rnd , int lf , int rg , int k){    if( lf == rg )        return  lf ;    //printf("%d %d   lf = %d   rg = %d\n  k = %d" , Lnd , Rnd , lf , rg , k) ;    Lnd = ( Lnd == NULL ? &w[0] : Lnd ) ;    //Rnd = ( Rnd == NULL ? &w[0] : Rnd ) ;    int Lt = 0 ;    if( Rnd->ls ) Lt += Rnd->ls->siz ;    if( Lnd->ls ) Lt -= Lnd->ls->siz ;    //printf("Lt = %d\n" , Lt) ;    int mid = ( lf + rg ) >> 1 ;     if( k > Lt )    return Query( Lnd->rs , Rnd->rs , mid + 1 , rg , k - Lt ) ;    else            return Query( Lnd->ls , Rnd->ls , lf , mid , k ) ;}void solve(){    int L , R , k ;    w[0] = node() ;    for( int i = 1 ; i <= N ; i ++ )        Insert( root[i - 1] , root[i] , 1 , siz , ns[i] );    for( int i = 1 ; i <= M ; i ++ ){        scanf( "%d%d%d" , &L , &R , &k ) ;        printf( "%d\n", arcns[ Query( root[ L - 1 ] , root[R] , 1 , siz , k ) ] );    }}int main(){    std::ios::sync_with_stdio(false);    scanf( "%d%d" , &N , &M ) ;    read_uniq() ;    solve() ;    return 0 ;}
原创粉丝点击