经典的带改动求区间第k小值问题
树套树模板,我是用的线段树套splay实现的,并且用的数组模拟的,所以可能空间略大,bzoj过了,zoj过不了。
思路非常easy,用线段树维护区间,用splay维护区间内的权值,然后询问的时候,二分答案key,然后在区间内找小于key的数有多少个。
贴上模板:
#include<stdio.h> #include<string.h> #include<algorithm> #define lson l , m , rt<<1 #define rson m + 1 , r , rt<<1|1 #define ls son[0][rt] #define rs son[1][rt] using namespace std ; const int maxn = 100001 ; const int N = maxn*18 ; const int INF = 1111111111 ; int a[maxn] , n , pool[N] , top ; struct TTT { int son[2][N] , size[N] , fa[N] , val[N] ; int root[N] , tot ; void push_up ( int rt ) { size[rt] = size[ls] + size[rs] + 1 ; } int new_node ( int _val ) { int rt ; if ( top ) rt = pool[top--] ; else rt = ++tot ; size[rt] = 1 ; ls = rs = fa[rt] = 0 ; val[rt] = _val ; return rt ; } void build_root ( int rt ) { rs = new_node ( INF ) ; fa[rs] = rt ; } void build ( int l , int r , int rt ) { root[rt] = new_node(-INF) ; build_root ( root[rt] ) ; if ( l == r ) return ; int m = l + r >> 1 ; build ( lson ) ; build ( rson ) ; } void rot ( int rt ) { int y = fa[rt] , z = fa[y] , c = rt == son[0][y] ; son[!c][y] = son[c][rt] , fa[son[c][rt]] = y ; son[c][rt] = y , fa[y] = rt ; fa[rt] = z ; son[y==son[1][z]][z] = rt ; push_up ( y ) ; } void splay ( int rt , int to ) { while ( fa[rt] != to ) { int y = fa[rt] , z = fa[y] ; if ( z != to ) rot ( (rt==son[0][y])^(y==son[0][z]) ? rt : y ) ; rot ( rt ) ; } push_up ( rt ) ; } int find_smaller ( int rt , int v ) { int ret ; if ( val[rt] >= v ) { if ( !ls ) return rt ; ret = find_smaller ( ls , v ) ; } else { if ( !rs ) return rt ; ret = find_smaller ( rs , v ) ; if ( val[ret] >= v ) ret = rt ; } return ret ; } int find_left_most ( int rt ) { while ( ls ) rt = ls ; return rt ; } int count_smaller ( int rt , int v ) { if ( !rt ) return 0 ; if ( val[rt] < v ) return size[ls] + 1 + count_smaller ( rs , v ) ; else return count_smaller ( ls , v ) ; } void add ( int& rt , int v ) { rt = find_smaller ( rt , v ) ; splay ( rt , 0 ) ; int temp = find_left_most ( rs ) ; splay ( temp , rt ) ; son[0][temp] = new_node ( v ) ; fa[son[0][temp]] = temp ; push_up ( temp ) ; push_up ( rt ) ; } void print ( int rt ) { if ( !rt ) return ; printf ( "rt = %d , sz = %d\n" , rt , size[rt] ) ; printf ( "ls = %d , rs = %d , fa = %d , val = %d\n" , ls , rs , fa[rt] , val[rt] ) ; print ( ls ) ; print ( rs ) ; } void del ( int& rt , int v ) { rt = find_smaller ( rt , v ) ; splay ( rt , 0 ) ; int temp = find_left_most ( rs ) ; if ( val[temp] != v ) return ; splay ( temp , rt ) ; temp = find_left_most ( son[1][temp] ) ; splay ( temp , rt ) ; pool[++top] = son[0][temp] ; son[0][temp] = 0 ; push_up ( temp ) ; push_up ( rt ) ; } void update ( int pos , int v , int op , int l , int r , int rt ) { if ( op == 0 ) { add ( root[rt] , v ) ; } else del ( root[rt] , v ) ; if ( l == r ) return ; int m = l + r >> 1 ; if ( pos <= m ) update ( pos , v , op , lson ) ; else update ( pos , v , op , rson ) ; } int count ( int a , int b , int v , int l , int r , int rt ) { if ( a <= l && r <= b ) { int k = count_smaller ( root[rt] , v ) - 1 ; return k ; } int m = l + r >> 1 , ret = 0 ; if ( a <= m ) ret = count ( a , b , v , lson ) ; if ( m < b ) ret += count ( a , b , v , rson ) ; return ret ; } void init () { tot = 0 ; top = 0 ; build ( 1 , n , 1 ) ; for ( int i = 1 ; i <= n ; i ++ ) { // printf ( "a[%d] = %d\n" , i , a[i] ) ; update ( i , a[i] , 0 , 1 , n , 1 ) ; } } int ask ( int a , int b , int k ) { int l = 0 , r = 1000000000 ; while ( l <= r ) { int m = l + r >> 1 ; int cnt = count ( a , b , m , 1 , n , 1 ) ; // printf ( "m = %d , cnt = %d\n" , m , cnt ) ; if ( cnt <= k - 1 ) l = m + 1 ; else r = m - 1 ; // printf ( "l = %d , r = %d\n" , l , r ) ; } return r ; } void modify ( int pos , int num ) { update ( pos , a[pos] , 1 , 1 , n , 1 ) ; update ( pos , num , 0 , 1 , n , 1 ) ; a[pos] = num ; } } ttt ; int main () { int T , m ; // freopen ( "a.in" , "r" , stdin ) ; // scanf ( "%d" , &T ) ; while ( scanf ( "%d%d" , &n , &m ) != EOF ) { for ( int i = 1 ; i <= n ; i ++ ) scanf ( "%d" , &a[i] ) ; ttt.init () ; while ( m -- ) { char op[11] ; int x , y , z ; scanf ( "%s" , op ) ; if ( op[0] == 'Q' ) { scanf ( "%d%d%d" , &x , &y , &z ) ; printf ( "%d\n" , ttt.ask ( x , y , z ) ) ; } else { scanf ( "%d%d" , &x , &y ) ; ttt.modify ( x , y ) ; } } } return 0 ; }