hdu 4747 Mex (线段树)

hdu 4747 Mex (线段树)

不错的思维题,犀利的线段树。解题思路百度很多。。我那蹩脚的表达能力,就不误导大家了。

 

#include<stdio.h>

#include<string.h>

#include<algorithm>

#include<map>

#define ll long long

#define lson l , m , rt << 1

#define rson m + 1 , r , rt << 1 | 1

using namespace std ;



const int maxn = 222222 ;

map<int,int> mp ;

int col[maxn<<2] , b[maxn] , a[maxn] , mx[maxn<<2] ;

ll ans = 0 , sum[maxn<<2] ;

int nxt[maxn] ;



inline void push_up ( int rt ) {

    sum[rt] = sum[rt<<1] + sum[rt<<1|1] ;

    mx[rt] = mx[rt<<1|1] ;

}



void push_down ( int rt , int m ) {

    if ( col[rt] != -1 ) {

        int ls = rt << 1 , rs = rt << 1 | 1 ;

        mx[ls] = mx[rs] = col[ls] = col[rs] = col[rt] ;

        sum[ls] = (ll) col[ls] * ( m - ( m >> 1 ) ) ;

        sum[rs] = (ll) col[rs] * ( m >> 1 ) ;

        col[rt] = -1 ;

    }

}



void build ( int l , int r , int rt ) {

    col[rt] = -1 ;

    if ( l == r ) {

        mx[rt] = sum[rt] = b[l] ;

        return ;

    }

    int m = ( l + r ) >> 1 ;

    build ( lson ) ;

    build ( rson ) ;

    push_up ( rt ) ;

}



int find ( int l , int r , int rt , int v ) {

    if ( l == r ) return l ;

    push_down ( rt , r - l + 1 ) ;

    int m = ( l + r ) >> 1 ;

    if ( mx[rt<<1] >= v ) return find ( lson , v ) ;

    else return find ( rson , v ) ;

}



void update ( int a , int b , int c , int l , int r , int rt ) {

    if ( a <= l && r <= b ) {

        col[rt] = c ;

        sum[rt] = (ll) c * ( r - l + 1 ) ;

        mx[rt] = c ;

        return ;

    }

    push_down ( rt , r - l + 1 ) ;

    int m = ( l + r ) >> 1 ;

    if ( a <= m ) update ( a , b , c , lson ) ;

    if ( m < b ) update ( a , b , c , rson ) ;

    push_up ( rt ) ;

}



void update ( int a , int l , int r , int rt ) {

    if ( l == r ) {

        mx[rt] = -1 ;

        sum[rt] = 0 ;

        return ;

    }

    push_down ( rt , r - l + 1 ) ;

    int m = ( l + r ) >> 1 ;

    if ( a <= m ) update ( a , lson ) ;

    else update ( a , rson ) ;

    push_up ( rt ) ;

}



void solve ( int n ) {

    int i , j , k , l , r ;

    for ( i = 1 ; i <= n ; i ++ ) {

        ans += sum[1] ;

        update ( i , 1 , n , 1 ) ;

        r = nxt[i] ;

        if ( mx[1] < a[i] ) continue ;

        l = find ( 1 , n , 1 , a[i] ) ;

        if ( l <= r ) update ( l , r , a[i] , 1 , n , 1 ) ;

    }

}



int main () {

    int n , i , j , k ;

    while ( scanf ( "%d" , &n ) != EOF ) {

        if ( n == 0 ) break ;

        ans = 0 ;

        mp.clear () ;

        for ( i = 1 ; i <= n ; i ++ ) scanf ( "%d" , &a[i] ) ;

        mp[a[1]] = 1 ;

        if ( a[1] == 0 ) k = b[1] = 1 ;

        else k = b[1] = 0 ;

        for ( i = 2 ; i <= n ; i ++ ) {

            mp[a[i]] = 1 ;

            while ( mp[k] ) k ++ ;

            b[i] = k ;

        }

        mp.clear () ;

        for ( i = n ; i>= 1 ; i -- ) {

            if ( !mp[a[i]] ) nxt[i] = n ;

            else nxt[i] = mp[a[i]] - 1 ;

            mp[a[i]] = i ;

        }

        build ( 1 , n , 1 ) ;

        solve ( n ) ;

        printf ( "%I64d\n" , ans ) ;

    }

    return 0 ;

}


 

 

你可能感兴趣的:(HDU)