BZOJ-3249: [ioi2013]game(动态线段树套SBT)

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3249

官方题目和数据:http://www.ioi2013.org/competition/tasks/

刚开始以为怎么这么一道傻叉数据结构题怎么没有什么人去写,不就一裸线段树套线段树,或者线段树(动态建树)套平衡树,还是平衡树套平衡树还是线段树神马的啊,然后就开始狂码上半天sgt+splay,交上去,果断TLE,然后又试了各种常数优化,IO优化神马的都上了,还要跑了260s+(交了好几次,差不多总共TLE了5次,卡20min左右,BZOJ上的同学们对不起啊),BZOJ的时限只有250s,最后无语的把splay改成SBT一次就A了,快了一倍左右。(Splay树的巨大常数说多了都是泪啊。。。以后不是那种要翻转的区间维护我是不会写splay的就是了。。。)

NOI官网上的IOI题解里大神的题解说是trie套trie,太神奇实在没想通,trie树居然还有这种神奇功能(孤陋寡闻啊我)。

代码(百度空间脑残了,贴不了这么长的高亮代码,贴代码的功能高亮又不知道哪里去了。。。QaQ):

c75c10385343fbf25afdea4bb27eca8064388f81.jpg.png
#include <cstdio>

#include <algorithm>

#include <cstring>

 

using namespace std ;

 

#define MAXN 3000100

#define L( t ) left[ t ]

#define R( t ) right[ t ]

#define Gcd( t ) Gcd[ t ]

#define Max( t ) Max[ t ]

#define Min( t ) Min[ t ]

#define V( t ) value[ t ]

#define K( t ) key[ t ]

#define S( t ) size[ t ]

#define inf 0x7fffffff

#define ll long long

 

void getint( int &t ) {

    int ch ; for ( ch = getchar(  ) ; ! ( ch >= '0' && ch <= '9' ) ; ch = getchar(  ) ) ;

    t = ch - '0' ;

    for ( ch = getchar(  ) ; ch >= '0' && ch <= '9' ; ch = getchar(  ) ) t *= 10 , t += ch - '0' ;

}

  

void getll( ll &t ) {

    int ch ; for ( ch = getchar(  ) ; ! ( ch >= '0' && ch <= '9' ) ; ch = getchar(  ) ) ;

    t = ch - '0' ;

    for ( ch = getchar(  ) ; ch >= '0' && ch <= '9' ; ch = getchar(  ) ) t *= 10 , t += ch - '0' ;

}

  

int ans[ 20 ] ;

  

void putll( ll t ) {

    if ( ! t ) putchar( '0' ) ; else {

        ans[ 0 ] = 0 ;

        for ( ; t ; t /= 10 ) ans[ ++ ans[ 0 ] ] = t % 10 ;

        while ( ans[ 0 ] ) putchar( '0' + ans[ ans[ 0 ] -- ] ) ;

    }

    putchar( '\n' ) ;

}

 

struct Pos {

    int x , y ;

    bool operator < ( const Pos &a ) const {

        return y < a.y || ( y == a.y && x < a.x ) ;

    }

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

        return x == a.x && y == a.y ;

    }

    bool operator > ( const Pos &a ) const {

        return y > a.y ||( y == a.y && x > a.x ) ;

    }

} key[ MAXN ] , Max[ MAXN ] , Min[ MAXN ] ;

 

Pos make( int _x , int _y ) {

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

    return u ;

}

 

int left[ MAXN ] , right[ MAXN ] , size[ MAXN ] , Node = 0 ;

ll value[ MAXN ] , Gcd[ MAXN ] ;

 

ll gcd( ll x , ll y ) {

    if ( x < y ) swap( x , y ) ;

    ll k ;

    while ( y ) {

        k = y ;

        y = x % y ;

        x = k ;

    }

    return x ;

}

 

void update( int t ) {

    if ( ! t ) return ;

    Gcd( t ) = gcd( gcd( Gcd( L( t ) ) , Gcd( R( t ) ) ) , V( t ) ) ;

    S( t ) = S( L( t ) ) + S( R( t ) ) + 1 ;

    Max( t ) = R( t ) ? Max( R( t ) ) : K( t ) ;

    Min( t ) = L( t ) ? Min( L( t ) ) : K( t ) ;

}

 

void left_ratote( int &t ) {

    int k = R( t ) ;

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

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

    t = k ;

}

 

void right_ratote( 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_ratote( t ) ;

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

        return ;

    }

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

        left_ratote( t ) ;

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

        return ;

    }

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

        left_ratote( L( t ) ) ; right_ratote( t ) ;

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

        return ;

    }

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

        right_ratote( R( t ) ) ; left_ratote( t ) ;

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

        return ;

    }

}

 

void Insert( Pos k , ll v , int &t ) {

    if ( ! t ) {

        t = ++ Node ;

        S( t ) = 1 , L( t ) = R( t ) = 0 , V( t ) = Gcd( t ) = v , K( t ) = Max( t ) = Min( t ) = k ;

        return ;

    }

    if ( k == K( t ) ) {

        V( t ) = v ; update( t ) ; return ;

    }

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

    update( t ) ; maintain( t ) ;

}

 

ll query( Pos l , Pos r , int t ) {

    if ( ! t ) return 0 ;

    if ( ! ( Min[ t ] < l ) && ! ( Max[ t ] > r ) ) return Gcd( t ) ;

    if ( r < K( t ) ) return query( l , r , L( t ) ) ;

    if ( l > K( t ) ) return query( l , r , R( t ) ) ;

    ll rec = V( t ) ;

    if ( l < K( t ) ) rec = gcd( rec , query( l , Max[ L( t ) ] , L( t ) ) ) ;

    if ( r > K( t ) ) rec = gcd( rec , query( Min[ R( t ) ] , r , R( t ) ) ) ;

    return rec ;

}

 

struct Node_sgt {

    Node_sgt *left , *right ;

    int roof ;

} *sgt , *null = new( Node_sgt ) ;

 

void Init_sgt_sbt(  ) {

    sgt = null -> left = null -> right = null , null -> roof = 0 ;

    L( 0 ) = R( 0 ) = S( 0 ) = V( 0 ) = Gcd( 0 ) = 0 , Max( 0 ) = make( - inf , - inf ) , Min( 0 ) = make( inf , inf ) ;

}

 

void Change( int l , int r , int x , int y , ll v , Node_sgt *&t ) {

    if ( t == null ) {

        t = new( Node_sgt ) ;

        t -> left = t -> right = null , t -> roof = 0 ;

    }

    Insert( make( x , y ) , v , t -> roof ) ;

    if ( l == r ) return ;

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

    if ( x <= mid ) Change( l , mid , x , y , v , t -> left ) ; else

    Change( mid + 1 , r , x , y , v , t -> right ) ;

}

 

ll Query( int l , int r , int x0 , int y0 , int x1 , int y1 , Node_sgt *t ) {

    if ( l == x0 && r == x1 ) return query( make( x0 , y0 ) , make( x1 , y1 ) , t -> roof ) ;

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

    if ( x1 <= mid ) return Query( l , mid , x0 , y0 , x1 , y1 , t -> left ) ;

    if ( x0 > mid ) return Query( mid + 1 , r , x0 , y0 , x1 , y1 , t -> right ) ;

    return gcd( Query( l , mid , x0 , y0 , mid , y1 , t -> left ) , Query( mid + 1 , r , mid + 1 , y0 , x1 , y1 , t -> right ) ) ;

}

 

int n , m , q ;

 

int main(  ) {

    Init_sgt_sbt(  ) ;

    getint( n ) , getint( m ) , getint( q ) ;

    while ( q -- ) {

        int x ; getint( x ) ;

        if ( x == 1 ) {

            int px , py ; ll pv ; getint( px ) , getint( py ) ; getll( pv ) ;

            Change( 0 , n - 1 , px , py , pv , sgt ) ;

        } else {

            int x0 , x1 , y0 , y1 ; getint( x0 ) , getint( y0 ) , getint( x1 ) , getint( y1 ) ;

            putll( Query( 0 , n - 1 , x0 , y0 , x1 , y1 , sgt ) ) ;

        }

    }

    return 0 ;

}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容

  • 一 什么是线段树? 线段树也叫区间树;线段树是一种二叉搜索树,它将一个区间划分成一些单元区间,每个单元区间对应线段...
    十丈_红尘阅读 1,237评论 0 3
  • 一年计划 From 2018.6.28 To 2019.7.30 引言 现在是2018年6月28日20:48突发奇...
    wawawa8阅读 423评论 0 0
  • 大家一听,急忙放下手中的活,围住小诺,眼里满是关切。 小诺格外感动,温声道:“我没事,大家不要担心,我睡一觉...
    梦无期1987阅读 257评论 2 2
  • 文/辛超凡 小时候的我们,虽然个子低,但是梦想很高很高。 老师长辈问我们:“你们长大想要做什么工作啊?”我们一定会...
    拾月星河阅读 302评论 5 4
  • 我国是一个糖尿病人群居世界前列的国家,这些人群对食物的控制尤为严格,比如米饭不能吃饱,水果不能吃多,甜品基本不能碰...
    tanao1405阅读 348评论 0 0