zoukankan      html  css  js  c++  java
  • BZOJ 1036: [ZJOI2008]树的统计Count( 树链剖分 )

     树链剖分...

     不知道为什么跑这么慢 = = 调了一节课啊跪..

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

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #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 L( x ) ( x << 1 )
    #define R( x ) ( L( x ) ^ 1 )
    #define mid( l , r ) ( ( l + r ) >> 1 )
    #define LC( x ) tree[ L( x ) ]
    #define RC( x ) tree[ R( x ) ]
    #define REP( x ) for( edge* e = head[ x ] ; e ; e = e -> next )
     
    using namespace std;
     
    const int maxn = 30000 + 5;
    const int inf = 0x7fffffff;
     
    int fa[ maxn ] , w[ maxn ] , size[ maxn ] , dep[ maxn ] , top[ maxn ] , son[ maxn ];
    int id_cnt = 0 , id[ maxn ] , id_r[ maxn ];
    int n;
     
    struct edge {
    int to;
    edge* next;
    };
     
    edge* pt , EDGE[ maxn << 1 ];
    edge* head[ maxn ];
     
    void add( int u , int v ) {
    pt -> to = v;
    pt -> next = head[ u ];
    head[ u ] = pt++;
    }
     
    void init() {
    pt = EDGE;
    clr( head , 0 );
    }
     
    #define add_edge( u , v ) add( u , v ) , add( v , u )
     
    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 );
    if( son[ x ] == -1 || size[ to ] > size[ son[ x ] ] )
       son[ x ] = to;
       
    size[ x ] += size[ to ];
    }
    }
     
    int TOP;
    void Dfs( int x ) {
    id[ x ] = ++id_cnt;
    id_r[ id[ x ] ] = x;
    top[ x ] = TOP;
    if( son[ x ] != -1 )
       Dfs( son[ x ] );
    REP( x ) if( id[ e -> to ] < 0 ) 
    Dfs( TOP = e -> to );
    }
     
    void _init() {
    clr( id , -1 );
    clr( son , -1 );
    dfs( dep[ 0 ] = 0 );
    Dfs( TOP = 0 );
    }
     
    struct Node {
    int l , r , Max , sum;
    };
     
    Node tree[ maxn << 4 ];
     
    int L , R , op;//1MAX 0 SUM
    int u , v;
     
    void maintain( int x ) {
    Node &o = tree[ x ];
    if( o. r > o.l ) {
    o.sum = LC( x ).sum + RC( x ).sum;
    o.Max = max( LC( x ).Max , RC( x ).Max );
    }
    }
     
    void update( int x ) {
    Node &o = tree[ x ];
    if( o.l == L && o.r == L ) 
       o.sum = o.Max = R;
    else {
    int m = mid( o.l , o.r );
    update( L <= m ? L( x ) : R( x ) );
    maintain( x );
    }
    }
     
    int query( int x ) {
    Node &o = tree[ x ];
    if( L <= o.l && o.r <= R )
    return op ? o.Max : o.sum;
    int m = mid( o.l , o.r );
    int ans;
    if( ! op ) {
    ans = 0;
    if( L <= m ) ans += query( L( x ) );
    if( m < R ) ans += query( R( x ) );
    } else {
    ans = -inf;
    if( L <= m ) ans = max( ans , query( L( x ) ) );
    if( m < R ) ans = max( ans , query( R( x ) ) );
    }
    return ans;
    }
     
    void build( int x , int l , int r ) {
    Node &o = tree[ x ];
    o.l = l , o.r = r;
    if( l == r )
       o.Max = o.sum = w[ id_r[ l ] ];
    else {
    int m = mid( l , r );
    build( L( x ) , l , m );
    build( R( x ) , m + 1 , r );
    maintain( x );
    }
    }
     
    int Qsum() {
    int ans = op = 0;
    while( top[ u ] != top[ v ] ) {
    if( dep[ top[ u ] ] < dep[ top[ v ] ] ) 
       swap( u , v );
    L = id[ top[ u ] ] , R = id[ u ];
    ans += query( 1 );
    u = fa[ top[ u ] ];
    }
    if( dep[ u ] > dep[ v ] ) swap( u , v );
    L = id[ u ] , R = id[ v ];
    return ans + query( 1 );
    }
     
    int Qmax() {
    int ans = -inf;
    op = 1;
    while( top[ u ] != top[ v ] ) {
    if( dep[ top[ u ] ] < dep[ top[ v ] ] ) 
       swap( u , v );
    L = id[ top[ u ] ] , R = id[ u ];
    ans = max( ans , query( 1 ) );
    u = fa[ top[ u ] ];
    }
    if( dep[ u ] > dep[ v ] ) swap( u , v );
    L = id[ u ] , R = id[ v ];
    return max( ans , query( 1 ) );
    }
     
    int main() {
    freopen( "test.in" , "r" , stdin );
    freopen( "test.out" ,"w" , stdout);
    init();
    cin >> n;
    rep( i , n - 1 ) {
    int u , v;
    scanf( "%d%d" , &u , &v );
    u-- , v--;
    add_edge( u , v );
    }
    rep( i , n ) scanf( "%d" , w + i );
    _init();
    build( 1 , 1 , n );
    int m;
    cin >> m;
    while( m-- ) {
    char s[ 10 ];
    scanf( " %s" , s );
    scanf( "%d%d" , &u , &v );
    u-- , v--;
    if( s[ 0 ] == 'C' ) {
    L = id[ u ];
    R = v + 1;
    update( 1 );
    } else {
    if( s[ 1 ] == 'S' ) printf( "%d " , Qsum() );
    else printf( "%d " , Qmax() );
    }
            
    }
       
    return 0;
    }

      

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

    1036: [ZJOI2008]树的统计Count

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 7694  Solved: 3155
    [Submit][Status][Discuss]

    Description

    一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身

    Input

    输入的第一行为一个整数n,表示节点的个数。接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。接下来1行,为一个整数q,表示操作的总数。接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。 对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。

    Output

    对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。

    Sample Input

    4
    1 2
    2 3
    4 1
    4 2 1 3
    12
    QMAX 3 4
    QMAX 3 3
    QMAX 3 2
    QMAX 2 3
    QSUM 3 4
    QSUM 2 1
    CHANGE 1 5
    QMAX 3 4
    CHANGE 3 6
    QMAX 3 4
    QMAX 2 4
    QSUM 3 4

    Sample Output

    4
    1
    2
    2
    10
    6
    5
    6
    5
    16

    HINT

    Source

  • 相关阅读:
    Linux 管道命令(pipe)
    SQLITE入门逐步讲解SQLITE命令行(二)
    用flash上传多个图片、文件的插件TinyBrowser
    PHP的时区问题GMT8
    解决Apache+PHP服务器提示HTTP 500问题
    SQLITE入门逐步讲解SQLITE命令行(四)
    SQLITE入门逐步讲解SQLITE命令行(五)
    linux tar命令使用范例
    SQLITE入门逐步讲解SQLITE命令行(六)
    Tinymce配置智能的Url
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/4570292.html
Copyright © 2011-2022 走看看