2300: [HAOI2011]防線修建(平衡樹動態(tài)維護凸包)

題目:http://www.lydsy.com/JudgeOnline/problem.php?id=2300

剛開始看到刪點不好操作,那么離線扎拣,然后變成加點秕磷,然后平衡樹動態(tài)維護凸包來搞曲秉。

代碼(SBT):

#include <cstdio>

#include <algorithm>

#include <cstring>

#include <cmath>

 

using namespace std ;

 

#define update( t ) S( t ) = S( L( t ) ) + S( R( t ) ) + 1

#define L( t ) left[ t ]

#define R( t ) right[ t ]

#define K( t ) key[ t ]

#define S( t ) size[ t ]

#define pre( t ) prefix[ t ]

#define suff( t ) suffix[ t ]

 

#define dist( p0 , p1 ) ( sqrt( ( p0.x - p1.x ) * ( p0.x - p1.x ) + ( p0.y - p1.y ) * ( p0.y - p1.y ) ) )

#define cal( p0 , p1 ) ( ( p0.y - p1.y ) / ( p0.x - p1.x ) )

#define Clear( x ) memset( x , 0 , sizeof( x ) )

 

const double esp = 0.000000001 ;

const int maxn = 100100 ;

const int maxm = 200100 ;

 

struct node {

    double x , y ;

    void print(  ) {

        printf( "( %.3f , %.3f )\n" , x , y ) ;

    }

    bool operator < ( const node &a ) const {

        return x - a.x < - esp ;

    }

    bool operator == ( const node &a ) const {

        return abs( x - a.x ) <= esp ;

    }

    bool operator > ( const node &a ) const {

        return x - a.x > esp ;

    }

} key[ maxn ] ;

 

node make( double _x , double _y ) {

    node u ;

    u.x = _x , u.y = _y ;

    return u ;

}

 

int left[ maxn ] , right[ maxn ] , size[ maxn ] , prefix[ maxn ] , suffix[ maxn ] , V , roof ;

 

int q[ maxm ][ 2 ] , n , m ;

double pos[ maxn ][ 2 ] , px , py , ans[ maxm ] , rec , h ;

bool f[ maxn ] ;

 

void Left( int &t ) {

    int k = R( t ) ;

    R( t ) = L( k ) ; update( t ) ;

    L( k ) = t ; update( k ) ;

    t = k ;

}

 

void Right( int &t ) {

    int k = L( t ) ;

    L( t ) = R( k ) ; update( t ) ;

    R( k ) = t ; update( k ) ;

    t = k ;

}

 

void maintain( int &t ) {

    if ( S( L( L( t ) ) ) > S( R( t ) ) ) {

        Right( t ) ;

        maintain( R( t ) ) ; maintain( t ) ;

        return ;

    }

    if ( S( R( L( t ) ) ) > S( R( t ) ) ) {

        Left( L( t ) ) ; Right( t ) ;

        maintain( L( t ) ) , maintain( R( t ) ) ; maintain( t ) ;

        return ;

    }

    if ( S( R( R( t ) ) ) > S( L( t ) ) ) {

        Left( t ) ;

        maintain( L( t ) ) ; maintain( t ) ;

        return ;

    }

    if ( S( L( R( t ) ) ) > S( L( t ) ) ) {

        Right( R( t ) ) ; Left( t ) ;

        maintain( L( t ) ) , maintain( R( t ) ) ; maintain( t ) ;

        return ;

    }

}

 

void Insert( node k , int &t ) {

    if ( ! t ) {

        t = ++ V ;

        S( t ) = 1 , K( t ) = k ;

        return ;

    }

    Insert( k , k < K( t ) ? L( t ) : R( t ) ) ;

    update( t ) ; maintain( t ) ;

}

 

void Delete( node k , int &t ) {

    if ( k == K( t ) ) {

        if ( ! L( t ) ) {

            t = R( t ) ; return ;

        } else if ( ! R( t ) ) {

            t = L( t ) ; return ;

        } else {

            Right( t ) ; Delete( k , R( t ) ) ;

        }

    } else Delete( k , k < K( t ) ? L( t ) : R( t ) ) ;

    update( t ) ; maintain( t ) ;

}

 

int Prefix( node k ) {

    int ret = 0 ;

    for ( int t = roof ; t ; t = k < K( t ) ? L( t ) : R( t ) ) if ( K( t ) < k ) {

        if ( ! ret || K( ret ) < K( t ) ) ret = t ;

    }

    return ret ;

}

 

int Suffix( node k ) {

    int ret = 0 ;

    for ( int t = roof ; t ; t = k < K( t ) ? L( t ) : R( t ) ) if ( K( t ) > k ) {

        if ( ! ret || K( ret ) > K( t ) ) ret = t ;

    }

    return ret ;

}

 

int Find( node k ) {

    for ( int t = roof ; t ; t = k < K( t ) ? L( t ) : R( t ) ) if ( K( t ) == k ) return t ;

    return 0 ;

}

 

void Push( node k ) {

    int t = Find( k ) ;

    if ( t ) {

        if ( K( t ).y >= k.y ) return ;

        rec -= ( dist( K( pre( t ) ) , K( t ) ) + dist( K( suff( t ) ) , K( t ) ) ) ;

        rec += dist( K( pre( t ) ) , K( suff( t ) ) ) ;

        suff( pre( t ) ) = suff( t ) , pre( suff( t ) ) = pre( t ) ;

        Delete( K( t ) , roof ) ;

    }

    int tp = Prefix( k ) , ts = Suffix( k ) ;

    if ( cal( K( tp ) , k ) <= cal( K( tp ) , K( ts ) ) ) return ;

    rec -= dist( K( tp ) , K( ts ) ) ;

    while ( K( tp ).x > esp ) {

        if ( cal( K( pre( tp ) ) , K( tp ) ) <= cal( K( tp ) , k ) ) {

            rec -= dist( K( pre( tp ) ) , K( tp ) ) ;

            Delete( K( tp ) , roof ) ;

        } else break ;

        tp = pre( tp ) ;

    }

    while ( h - K( ts ).x > esp ) {

        if ( cal( K( suff( ts ) ) , K( ts ) ) >= cal( K( ts ) , k ) ) {

            rec -= dist( K( suff( ts ) ) , K( ts ) ) ;

            Delete( K( ts ) , roof ) ;

        } else break ;

        ts = suff( ts ) ;

    }

    Insert( k , roof ) ;

    pre( suff( tp ) = V ) = tp , suff( pre( ts ) = V ) = ts ;

    rec += ( dist( K( tp ) , k ) + dist( K( ts ) , k ) ) ;

}

 

void Test( int t ) {

    for ( t = roof ; L( t ) ; t = L( t ) ) ;

    for ( ; t ; t = suff( t ) ) K( t ).print(  ) ;

}

 

int main(  ) {

    scanf( "%lf%lf%lf" , &h , &px , &py ) ;

    scanf( "%d" , &n ) ;

    memset( f , true , sizeof( f ) ) ;

    for ( int i = 0 ; i ++ < n ; ) scanf( "%lf%lf" , &pos[ i ][ 0 ] , &pos[ i ][ 1 ] ) ;

    scanf( "%d" , &m ) ;

    for ( int i = 0 ; i ++ < m ; ) {

        scanf( "%d" , &q[ i ][ 0 ] ) ;

        if ( q[ i ][ 0 ] == 1 ) {

            scanf( "%d" , &q[ i ][ 1 ] ) ;

            f[ q[ i ][ 1 ] ] = false ;

        }

    }

    Clear( left ) , Clear( right ) , Clear( size ) ;

    V = 3 ;

    S( roof = 2 ) = 3 ; K( roof ) = make( px , py ) , L( roof ) = pre( roof ) = 1 , R( roof ) = suff( roof ) = 3 ;

    S( 1 ) = S( 3 ) = 1 , suff( 1 ) = pre( 3 ) = 2 , K( 1 ) = make( 0 , 0 ) , K( 3 ) = make( h , 0 ) ;

    rec = dist( make( 0 , 0 ) , make( px , py ) ) + dist( make( px , py ) , make( h , 0 ) ) ;

    for ( int i = 0 ; i ++ < n ; ) if ( f[ i ] ) Push( make( pos[ i ][ 0 ] , pos[ i ][ 1 ] ) ) ;

    for ( int i = m ; i ; -- i ) {

        if ( q[ i ][ 0 ] == 1 ) {

            Push( make( pos[ q[ i ][ 1 ] ][ 0 ] , pos[ q[ i ][ 1 ] ][ 1 ] ) ) ;

        } else {

            ans[ i ] = rec ;

        }

//      printf( "\n\n%d:\n" , i ) ;

//      Test( roof ) ;

    }

    for ( int i = 0 ; i ++ < m ; ) if ( q[ i ][ 0 ] == 2 ) printf( "%.2f\n" , ans[ i ] ) ;

    return 0 ;

}
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市熊赖,隨后出現(xiàn)的幾起案子来屠,更是在濱河造成了極大的恐慌,老刑警劉巖震鹉,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件俱笛,死亡現(xiàn)場離奇詭異,居然都是意外死亡传趾,警方通過查閱死者的電腦和手機迎膜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來浆兰,“玉大人磕仅,你說我怎么就攤上這事∧魉希” “怎么了宽涌?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蝶棋。 經(jīng)常有香客問我卸亮,道長,這世上最難降的妖魔是什么玩裙? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任兼贸,我火速辦了婚禮,結果婚禮上吃溅,老公的妹妹穿的比我還像新娘溶诞。我一直安慰自己,他們只是感情好决侈,可當我...
    茶點故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布螺垢。 她就那樣靜靜地躺著,像睡著了一般赖歌。 火紅的嫁衣襯著肌膚如雪枉圃。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天庐冯,我揣著相機與錄音孽亲,去河邊找鬼。 笑死展父,一個胖子當著我的面吹牛返劲,可吹牛的內(nèi)容都是我干的玲昧。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼篮绿,長吁一口氣:“原來是場噩夢啊……” “哼孵延!你這毒婦竟也來了?” 一聲冷哼從身側響起搔耕,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤隙袁,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后弃榨,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體菩收,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年鲸睛,在試婚紗的時候發(fā)現(xiàn)自己被綠了娜饵。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡官辈,死狀恐怖箱舞,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情拳亿,我是刑警寧澤晴股,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站肺魁,受9級特大地震影響电湘,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜鹅经,卻給世界環(huán)境...
    茶點故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一寂呛、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧瘾晃,春花似錦贷痪、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至强胰,卻和暖如春尚镰,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背哪廓。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留初烘,地道東北人涡真。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓分俯,卻偏偏與公主長得像,于是被迫代替她去往敵國和親哆料。 傳聞我的和親對象是個殘疾皇子缸剪,可洞房花燭夜當晚...
    茶點故事閱讀 44,724評論 2 354

推薦閱讀更多精彩內(nèi)容