zoukankan      html  css  js  c++  java
  • BZOJ 3626: [LNOI2014]LCA( 树链剖分 + 离线 )

    说多了都是泪啊...调了这么久..

     离线可以搞 , 树链剖分就OK了...

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

    #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 mod( x ) ( ( x ) %= MOD )
    #define M( l , r ) ( ( l + r ) >> 1 )
    #define L( x ) ( ( x ) << 1 )
    #define R( x ) ( L( x ) ^ 1 )
     
    using namespace std;
     
    const int maxn = 50000 + 5;
    const int maxnode = 140000;
    const int MOD = 201314;
     
    int n;
      
    struct edge {
    int to;
    edge* next;
    };
     
    edge* pt , EDGE[ maxn ];
    edge* head[ maxn ];
     
    inline void add_edge( int u , int v ) {
    pt -> to = v;
    pt -> next = head[ u ];
    head[ u ] = pt++;
    }
     
    void edge_init() {
    pt = EDGE;
    clr( head , 0 );
    }
     
     
    int top[ maxn ] , fa[ maxn ] , son[ maxn ] , size[ maxn ];
     
    void dfs( int x ) {
    size[ x ] = 1;
    REP( x ) {
    int to = e -> to;
    dfs( to );
    size[ x ] += size[ to ];
    if( son[ x ] == -1 || size[ to ] > size[ son[ x ] ] )
       son[ x ] = to;
    }
    }
     
    int id[ maxn ] , id_cnt = 0;
    int TOP;
    void DFS( int x ) {
    id[ x ] = ++id_cnt;
    top[ x ] = TOP;
    if( son[ x ] != -1 )
       DFS( son[ x ] );
    REP( x ) if( e -> to != son[ x ] )
       DFS( TOP = e -> to );
    }
     
    void DFS_init() {
    clr( son , -1 );
    dfs( 0 );
    DFS( TOP = 0 );
    }
     
     
    int add[ maxnode ] , sum[ maxnode ];
    int L , R , query_ans;
     
    inline void maintain( int x , int l , int r ) {
    sum[ x ] = add[ x ] * ( r - l + 1 );
    if( r > l )
       sum[ x ] += sum[ L( x ) ] + sum[ R( x ) ];
    }
     
    void update( int x , int l , int r ) {
    if( L <= l && r <= R )
       add[ x ]++;
    else {
    int m = M( l , r );
    if( L <= m ) update( L( x ) , l , m );
    if( m < R) update( R( x) , m + 1 , r );
    }
    maintain( x , l , r );
    }
    inline void Update( int l , int r ) {
    L = l , R = r;
    update( 1 , 1 , n );
    }
     
    void query( int x , int l , int r , int Add ) {
    if( L <= l && r <= R ) 
       query_ans += sum[ x ] + Add * ( r - l + 1 );
    else {
    Add += add[ x ];
    int m = M( l , r );
    if( L <= m ) query( L( x ) , l , m , Add );
    if( m < R ) query( R( x ) , m + 1 , r , Add );
    }
    }
    inline int Query( int l , int r ) {
    query_ans = 0;
    L = l , R = r;
    query( 1 , 1 , n , 0 );
    return query_ans;
    }
     
    int Q( int x ) {
    int res = 0;
    while( top[ x ] != top[ 0 ] ) {
    mod( res += Query( id[ top[ x ] ] , id[ x ] ) );
    x = fa[ top[ x ] ];
    }
    return ( res + Query( id[ 0 ] , id[ x ] ) ) % MOD;
    }
     
    void modify( int x ) {
    while( top[ x ] != top[ 0 ] ) {
    Update( id[ top[ x ] ] , id[ x ] );
    x = fa[ top[ x ] ];
    }
    Update( id[ 0 ] , id[ x ] );
    }
     
     
    struct data {
    int x , num , s;
    bool operator < ( const data &rhs ) const {
    return x < rhs.x;
    }
    };
     
    data A[ maxn << 1 ];
    int z[ maxn ];
    int ans[ maxn ];
     
    int read() {
    int ans = 0;
    char c = getchar();
    while( ! isdigit( c ) ) c = getchar();
    while( isdigit( c ) ) {
    ans = ans * 10 + c - '0';
    c = getchar();
    }
    return ans;
    }
     
    int main() {
    freopen( "test.in" , "r" , stdin );
    n = read();
    int q = read();
    edge_init();
    Rep( i , n - 1 ) {
       fa[ i ] = read();
       add_edge( fa[ i ] , i );
    }
    rep( i , q ) {
    data &a = A[ i ] , &b = A[ i + q ];
    a.x = read() , b.x = read();
    *( z + i ) = read();
    a.x--;
    a.s = -1 , b.s = 1;
    a.num = b.num = i;
    }
    DFS_init();
    clr( sum , 0 );
    q <<= 1;
    sort( A , A + q );
    int cur = 0;
    clr( ans , 0 );
    for( ; cur < q && A[ cur ].x < 0 ; cur++ );
    rep( i , n ) {
    modify( i );
    for( ; cur < q , A[ cur ].x == i ; cur++ )
       mod( mod( ans[ A[ cur ].num ] += Q( z[ A[ cur ].num ] ) * A[ cur ].s ) += MOD );
    }
    q >>= 1;
    rep( i , q )
       printf( "%d " , ans[ i ] );
    return 0;
    }

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

    3626: [LNOI2014]LCA

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 855  Solved: 291
    [Submit][Status][Discuss]

    Description

    给出一个n个节点的有根树(编号为0到n-1,根节点为0)。一个点的深度定义为这个节点到根的距离+1。
    设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先。
    有q次询问,每次询问给出l r z,求sigma_{l<=i<=r}dep[LCA(i,z)]。
    (即,求在[l,r]区间内的每个节点i与z的最近公共祖先的深度之和)

    Input

    第一行2个整数n q。
    接下来n-1行,分别表示点1到点n-1的父节点编号。
    接下来q行,每行3个整数l r z。

    Output

    输出q行,每行表示一个询问的答案。每个答案对201314取模输出

    Sample Input

    5 2
    0
    0
    1
    1
    1 4 3
    1 4 2

    Sample Output

    8
    5

    HINT

    共5组数据,n与q的规模分别为10000,20000,30000,40000,50000。


    Source

  • 相关阅读:
    [java]java String.split()函数的用法分析
    [sql]java.sql.Types的具体对应值(jdbcType)
    [sql]join的5种方式:inner join、left(outer) join、right (outer) Join、full(outer) join、cross join
    [java]String和Date、Timestamp之间的转换
    [Eclipse]保存java文件时,自动删除不需要的包import
    [postgresql]ROWS is not applicable when function does not return a set问题解决
    [postgreSql]postgreSql数据库、模式、表、函数的删除与创建
    zbb20170816 oracle Oracle 查看表空间、数据文件的大小及使用情况sql语句
    zbb20170811 mysql远程连接报错: Host * is not allowed to connect to this MySQL server,解决方法
    zbb20170811 linux 给用户授予文件夹权限
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/4573581.html
Copyright © 2011-2022 走看看