第一次写主席树,比较畏惧,害怕又会因为一些小错误调试半天,就拿这玩意当模板题写了,然而并没有想象的困难。
抱怨几句
指针的写法要判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 ;
}