zoukankan      html  css  js  c++  java
  • BZOJ 2243: [SDOI2011]染色( 树链剖分 )

    树链剖分...细节挺多的...

    ---------------------------------------------------------------------------------

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
     
    #define rep( i , n ) for( int i = 0 ; i < n ; ++i )
    #define clr( x , c ) memset( x , c , sizeof( x ) )
    #define Rep( i , n ) for( int i = 1 ; i <= n ; ++i )
    #define REP( x ) for( edge* e = head[ x ] ; e ;e = e -> next )
    #define M( l , r ) ( ( l + r ) >> 1 )
    #define L( x ) ( ( x ) << 1 )
    #define R( x ) ( L( x ) ^ 1 )
    #define LC L( x ) , l , m
    #define RC R( x ) , m + 1 , r
    #define X x , l , r
    #define XX int x , int l , int r 
    #define All 1 , 1 , n
     
    using namespace std;
     
    const int maxn = 100000 + 5;
    const int maxnode = 270000;
     
     
    int n;
    int seq[ maxn ];
     
     
    struct edge {
    int to;
    edge* next;
    };
     
    edge* pt , EDGE[ maxn << 1 ];
    edge* head[ maxn ];
     
    void edge_init() {
    pt = EDGE;
    clr( head , 0 );
    }
     
    void add( int u , int v ) {
    pt -> to = v;
    pt -> next = head[ u ];
    head[ u ] = pt++;
    }
    #define add_edge( u , v ) add( u , v ) , add( v , u )
     
     
     
     
     
    int top[ maxn ] , fa[ maxn ] , dep[ maxn ] , size[ maxn ] , son[ maxn ];
    int id[ maxn ] , _id[ maxn ] , id_cnt = 0 , TOP;
     
    void dfs( int x ) {
    size[ x ] = 1;
    REP( x ) {
    int to = e -> to;
    if( to == fa[ x ] ) continue;
    dep[ to ] = dep[ x ] + 1;
    fa[ to ] = x;
    dfs( to );
    size[ x ] += size[ to ];
    if( son[ x ] == -1 || size[ to ] > size[ son[ x ] ] )
       son[ x ] = to;
    }
    }
     
    void DFS( int x ) {
    id[ x ] = ++id_cnt;
    _id[ id_cnt ] = x;
    top[ x ] = TOP;
    if( son[ x ] != -1 )
       DFS( son[ x ] );
    REP( x ) if( id[ e -> to ] < 0 )
       DFS( TOP = e -> to );
    }
    void DFS_init() {
    clr( id , -1 );
    clr( son , -1 );
    dfs( dep[ 0 ] = 0 );
    DFS( TOP = 0 );
    }
     
     
     
     
    int l_c[ maxnode ] , r_c[ maxnode ] , sum[ maxnode ] , set[ maxnode ];
    int L , R , v , query_ans , find_id;
     
    void maintain( XX ) {
    if( set[ x ] >= 0 || l == r ) {
    l_c[ x ] = r_c[ x ] = set[ x ];
       sum[ x ] = 1;
    } else {
    sum[ x ] = sum[ L( x ) ] + sum[ R( x ) ] - ( r_c[ L( x ) ] == l_c[ R( x ) ] );
    l_c[ x ] = l_c[ L( x ) ];
    r_c[ x ] = r_c[ R( x ) ];
    }
    }
     
    void pushdown( XX ) {
    if( set[ x ] >= 0 ) {
    set[ L( x ) ] = set[ R( x ) ] = set[ x ];
    l_c[ L( x ) ] = l_c[ R( x ) ] = l_c[ x ];
    r_c[ L( x ) ] = r_c[ R( x ) ] = r_c[ x ];
    set[ x ] = -1;
    }
    }
     
    void update( XX ) {
    if( L <= l && r <= R ) {
    set[ x ] = l_c[ x ] = r_c[ x ] = v;
    sum[ x ] = 1;
    } else {
    int m = M( l , r );
    pushdown( X );
    maintain( LC );
    maintain( RC );
    if( L <= m ) update( LC );
    if( m < R ) update( RC );
    maintain( X );
    }
    }
    void Update( int l , int r ) {
    L= l , R = r;
    update( All );
    }
     
    void query( XX ) {
    if( L <= l && r <= R ) {
    query_ans += sum[ x ];
    } else {
    int m = M( l , r ) , t[ 2 ] = { -1 , -1 };
    pushdown( X );
    maintain( LC );
    maintain( RC );
    if( L <= m ) 
       query( LC ) , t[ 0 ] = r_c[ L( x ) ];
    if( m < R ) 
       query( RC ) , t[ 1 ] = l_c[ R( x ) ];
    if( t[ 0 ] == t[ 1 ] && t[ 0 ] != -1 )
       query_ans--;
    }
    }
    int Query( int l , int r ) {
    L = l , R = r;
    query_ans = 0;
    query( All );
    return query_ans;
    }
     
    int find( XX ) {
    if( l == r ) 
       return set[ x ];
    int m = M( l , r );
    pushdown( X );
    maintain( LC );
    maintain( RC );
    return find_id <= m ? find( LC ) : find( RC );
    }
    int Find( int v ) {
    find_id = v;
    return find( All );
    }
     
     
    void build( XX ) {
    if( l == r ) {
    sum[ x ] = 1;
    set[ x ] = l_c[ x ] = r_c[ x ] = seq[ _id[ l ] ];
    } else {
    set[ x ] = -1;
    int m = M( l , r );
    build( LC );
    build( RC );
    maintain( X );
    }
    }
     
     
     
    void modify( int x , int y ) {
    while( top[ x ] != top[ y ] ) {
    if( dep[ top[ x ] ] < dep[ top[ y ] ] )
       swap( x , y );
    Update( id[ top[ x ] ] , id[ x ] );
    x = fa[ top[ x ] ];
    }
    if( dep[ x ] > dep[ y ] ) 
       swap( x , y );
    Update( id[ x ] , id[ y ] );
    }
     
    int Q( int x , int y ) {
    int res = 0;
    while( top[ x ] != top[ y ] ) {
    if( dep[ top[ x ] ] < dep[ top[ y ] ] )
       swap( x , y );
    res += Query( id[ top[ x ] ] , id[ x ] );
    int t[ 2 ] = { Find( id[ fa[ top[ x ] ] ] ) , Find( id[ top[ x ] ] ) };
    if( t[ 0 ] == t[ 1 ] ) res--;
    x = fa[ top[ x ] ];
    }
    if( dep[ x ] > dep[ y ] ) 
       swap( x , y );
    return res + Query( id[ x ] , id[ y ] );
    }
     
     
    int main() {
    freopen( "test.in" , "r" , stdin );
    freopen( "test.out" , "w" , stdout );
    int m;
    cin >> n >> m;
    rep( i , n )
       scanf( "%d" , seq + i );
    edge_init();
    rep( i , n - 1 ) {
    int u , v;
    scanf( "%d%d" , &u , &v );
    u-- , v--;
    add_edge( u , v );
    }
    DFS_init();
    build( 1 , 1 , n );
    while( m-- ) {
    char type;
    int x , y;
    scanf( " %c%d%d" , &type , &x , &y );
    x-- , y--;
    if( type == 'C' ) {
    scanf( "%d" , &v );
    modify( x , y );
    } else
    printf( "%d " , Q( x , y ) );
    }
    return 0;
    }

    --------------------------------------------------------------------------------- 

    2243: [SDOI2011]染色

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 3239  Solved: 1249
    [Submit][Status][Discuss]

    Description

    给定一棵有n个节点的无根树和m个操作,操作有2类:

    1、将节点a到节点b路径上所有点都染成颜色c

    2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“1122213段组成:“11、“222和“1

    请你写一个程序依次完成这m个操作。

    Input

    第一行包含2个整数nm,分别表示节点数和操作数;

    第二行包含n个正整数表示n个节点的初始颜色

    下面 行每行包含两个整数xy,表示xy之间有一条无向边。

    下面 行每行描述一个操作:

    “C a b c”表示这是一个染色操作,把节点a到节点b路径上所有点(包括ab)都染成颜色c

    “Q a b”表示这是一个询问操作,询问节点a到节点b(包括ab)路径上的颜色段数量。

    Output

    对于每个询问操作,输出一行答案。

    Sample Input

    6 5

    2 2 1 2 1 1

    1 2

    1 3

    2 4

    2 5

    2 6

    Q 3 5

    C 2 1 1

    Q 3 5

    C 5 1 2

    Q 3 5

    Sample Output

    3

    1

    2

    HINT

    数N<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。

    Source

  • 相关阅读:
    验证整数或小数
    数据库的连接查询比较
    批处理按钮
    事务 SQL
    关于GridView模板的一些总结
    C#数据结构之线性表
    C#面向对象基础
    C#集合类:动态数组、队列、栈、哈希表、字典
    如何更改master中WebParts中自定义控件的值。
    如何取得web.config中connectings中的值
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/4574411.html
Copyright © 2011-2022 走看看