zoukankan      html  css  js  c++  java
  • BZOJ 2631: tree( LCT )

    LCT...略麻烦...

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

    #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 ) )
      
    using namespace std;
     
    const int maxn = 100000 + 5;
    const int maxnode = maxn + 100;
    const int MOD = 51061;
    const int maxedge = maxn << 1;
     
    #define mod( x ) ( ( x ) %= MOD )
     
    int n;
     
    struct edge {
    int to;
    edge* next;
    };
     
    edge* head[ maxn ];
    edge EDGE[ maxedge ];
    edge* e_pt;
     
    void add( int u , int v ) {
    e_pt -> to = v;
    e_pt -> next = head[ u ];
    head[ u ] = e_pt++;
    }
     
    #define add_edge( u , v ) add( u , v ) , add( v , u )
     
    void edge_init() {
    e_pt = EDGE;
    clr( head , 0 );
    }
     
    struct Node *pt , *null;
     
    struct Node {
    Node *ch[ 2 ] , *p , *fa;
    int add , mul , sum , v , s;
    bool isRoot , rev;
    Node() : v( 1 ) , add( 0 ) , mul( 1 ) , sum( 1 ) , s( 1 ) {
    ch[ 0 ] = ch[ 1 ] = p = fa = null;
    isRoot = true;
    rev = false;
    }
    inline void setc( Node* c , int d ) {
    ch[ d ] = c;
    c -> p = this;
    }
    inline bool d() {
    return this == p -> ch[ 1 ];
    }
    inline void relax() {
    if( rev ) {
    rev = false;
    rep( i , 2 ) if( ch[ i ] != null )
       ch[ i ] -> Rev();
    }
    if( mul != 1 ) {
    rep( i , 2 ) if( ch[ i ] != null ) 
       ch[ i ] -> Mul( mul );
    mul = 1;
    }
    if( add ) {
    rep( i , 2 ) if( ch[ i ] != null )
       ch[ i ] -> Add( add );
    add = 0;
    }
    }
    inline void upd() {
    s = ch[ 0 ] -> s + ch[ 1 ] -> s + 1;
    mod( sum = ch[ 0 ] -> sum + v + ch[ 1 ] -> sum );
    }
    inline void Rev() {
    rev ^= 1;
    swap( ch[ 0 ] , ch[ 1 ] );
    }
    inline void Add( int ad ) {
    mod( add += ad );
    mod( sum += 1LL * ad * s % MOD );
    mod( v += ad );
    }
    inline void Mul( int mu ) {
    add = 1LL * add * mu % MOD;
    mul = 1LL * mul * mu % MOD;
    sum = 1LL * sum * mu % MOD;
    v = 1LL * v * mu % MOD;
    }
    inline void setRoot() {
    fa = p;
    p = null;
    isRoot = true;
    }
    void* operator new( size_t ) {
    return pt++;
    }
    };
     
    Node NODE[ maxnode ];
    void rot( Node* t ) {
    Node* p = t -> p;
    p -> relax();
    t -> relax();
    int d = t -> d();
    p -> p -> setc( t , p -> d() );
    p -> setc( t -> ch[ d ^ 1 ] , d );
    t -> setc( p , d ^ 1 );
    p -> upd();
    if( p -> isRoot ) {
    p -> isRoot = false;
    t -> isRoot = true;
    t -> fa = p -> fa;
    }
    }
     
    void splay( Node* t , Node* f = null ) {
    static Node* S[ maxn ];
    int top = 0;
    for( Node* o = t ; o != null ; o = o -> p ) S[ ++top ] = o;
    while( top ) S[ top-- ] -> relax();
    for( Node* p = t -> p ; p != f ; p = t -> p ) {
    if( p -> p != f )
       p -> d() != t -> d() ? rot( t ) : rot( p );
    rot( t );
    }
    t -> upd();
    }
     
    void access( Node* t ) {
    for( Node* o = null ; t != null ; o = t , t = t -> fa ) {
    splay( t );
    t -> ch[ 1 ] -> setRoot();
    t -> setc( o , 1 );
    }
    }
     
    void makeRoot( Node* t ) {
    access( t );
    splay( t );
    t -> Rev();
    }
     
    Node* findRoot( Node* t ) {
    access( t );
    splay( t );
    for( ; t -> ch[ 0 ] != null ; t = t -> ch[ 0 ] )
       t -> relax();
    splay( t );
    return t;
    }
     
    void cut( Node* x , Node* y ) {
    makeRoot( x );
    access( y );
    splay( x );
    x -> setc( null , 1 );
    x -> upd();
    y -> p = null;
    y -> setRoot();
    }
     
    void join( Node* x , Node* y ) {
    makeRoot( x );
    x -> fa = y;
    }
     
    Node* get( Node* x , Node* y ) {
    makeRoot( x );
    access( y );
    splay( y );
    return y;
    }
     
    void node_init() {
    pt = NODE;
    null = new( Node );
    null -> s = null -> v = null -> sum = 0;
    }
     
    Node* V[ maxn ];
     
    void dfs( int x , int par ) {
    for( edge* e = head[ x ] ; e ; e = e -> next ) {
    int to = e -> to;
    if( to == par ) continue;
    dfs( to , x );
    V[ to ] -> fa = V[ x ];
    }
    }
     
    void build_tree() {
    rep( i , n ) V[ i ] = new( Node );
    dfs( 0 , -1 );
    }
     
    int main() {
    freopen( "test.in" , "r" , stdin );
    freopen( "test.out" , "w" , stdout );
    edge_init();
    node_init();
    int q , u , v;
    cin >> n >> q;
    rep( i , n - 1 ) {
    scanf( "%d%d" , &u , &v );
    u-- , v--;
    add_edge( u , v );
    }
    build_tree();
    char op;
    while( q-- ) {
    scanf( " %c%d%d" , &op , &u , &v );
    u-- , v--;
    if( op == '-' ) {
    cut( V[ u ] , V[ v ] );
    scanf( "%d%d" , &u , &v );
    u-- , v--;
    join( V[ u ] , V[ v ] );
    } else if( op == '/' ) {
    printf( "%d " , get( V[ u ] , V[ v ] ) -> sum );
    } else {
    int c;
    scanf( "%d" , &c );
    mod( c );
    op != '+' ? get( V[ u ] , V[ v ] ) -> Mul( c ) : get( V[ u ] , V[ v ] ) -> Add( c );
    }
    }
    return 0;
    }

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

    2631: tree

    Time Limit: 30 Sec  Memory Limit: 128 MB
    Submit: 2454  Solved: 819
    [Submit][Status][Discuss]

    Description

     一棵n个点的树,每个点的初始权值为1。对于这棵树有q个操作,每个操作为以下四种操作之一:
    + u v c:将u到v的路径上的点的权值都加上自然数c;
    - u1 v1 u2 v2:将树中原有的边(u1,v1)删除,加入一条新边(u2,v2),保证操作完之后仍然是一棵树;
    * u v c:将u到v的路径上的点的权值都乘上自然数c;
    / u v:询问u到v的路径上的点的权值和,求出答案对于51061的余数。

    Input

      第一行两个整数n,q
    接下来n-1行每行两个正整数u,v,描述这棵树
    接下来q行,每行描述一个操作

    Output

      对于每个/对应的答案输出一行

    Sample Input

    3 2
    1 2
    2 3
    * 1 3 4
    / 1 1

    Sample Output

    4


    HINT

    数据规模和约定

    10%的数据保证,1<=n,q<=2000

    另外15%的数据保证,1<=n,q<=5*10^4,没有-操作,并且初始树为一条链

    另外35%的数据保证,1<=n,q<=5*10^4,没有-操作

    100%的数据保证,1<=n,q<=10^5,0<=c<=10^4


    Source

  • 相关阅读:
    一文读懂比特币的软分叉
    区块链的七阶段位,你属于哪一段?
    总价值超26.7亿美元的5个最富有比特币地址汇总
    智能合约的沙箱机制是什么?
    区块链的核心技术是什么?
    区块链和比特币常见的七大误区
    矿机论斤卖?夸大其词
    比特币跌破5000美元的三大影响因素
    微软Azure区块链开发工具包三大功能详解
    各大自媒体平台的收益情况汇总
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/4598647.html
Copyright © 2011-2022 走看看