您的位置:首页 > 其它

[POJ2104] 主席树模板题

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

抱怨几句

指针的写法要判NULL真的麻烦= =

随便写什么树一眼望过去全是

if(XXXX!=NULL)


关于题目

题目连接:POJ2104

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

分析与思路

感觉没有什么可以说的····

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

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

from Oyking cnblogs

细节看代码。

代码

Problem: 2104       User: Nafario
Memory: 49140K      Time: 2469MS
Language: 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 ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: