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

  • 相关阅读:
    新一代MQ apache pulsar的架构与核心概念
    Flutter使用fluwx实现微信分享
    BZOJ3622 已经没有什么好害怕的了 动态规划 容斥原理 组合数学
    NOIP2016提高组Day1T2 天天爱跑步 树链剖分 LCA 倍增 差分
    Codeforces 555C Case of Chocolate 其他
    NOIP2017提高组Day2T3 列队 洛谷P3960 线段树
    NOIP2017提高组Day2T2 宝藏 洛谷P3959 状压dp
    NOIP2017提高组Day1T3 逛公园 洛谷P3953 Tarjan 强连通缩点 SPFA 动态规划 最短路 拓扑序
    Codeforces 873F Forbidden Indices 字符串 SAM/(SA+单调栈)
    Codeforces 873E Awards For Contestants ST表
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/4574411.html
Copyright © 2011-2022 走看看