zoukankan      html  css  js  c++  java
  • 8.4 POJ 3237 (树链剖分+线段树

    题意:边权树链剖分 ,三种操作

    1.CHANGE把第i条边的权值改为a

    2.NEGATE把第a个点到第b个点的边的权值全部取相反数

    3.QUERY求第a个点到第b个点的最大边权。

    分析:

    这次是没看板子自己默的树链剖分哈哈

    意料之中的出现了错误:

    1.链式前向星用的不熟,之前都是vector存边的 ,但poj上的树链剖分题好像vectoc会超时

    2.取反的lazy标记更新要考虑负负得正

    这种复杂一点的线段树用struct存就写的比较清楚,比数组好一些

    //树链剖分 b
    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    
    #define fi first
    #define se second
    #define rep( i ,x ,y ) for( int i= x; i<= y ;i++ )
    #define reb( i ,y ,x ) for( int i= y; i>= x ;i-- )
    #define mem( a ,x ) memset( a ,x ,sizeof(a))
    #define li i<<1
    #define ri i<<1|1
    using namespace std;
    
    typedef long long ll;
    typedef long double ld;
    typedef pair<int ,int> pii;
    typedef pair<ll ,ll> pll;
    typedef pair<string ,int> psi;
    
    const int inf = 0x3f3f3f3f;
    const int N = 100005;
    const int M = 1000005;
    
    struct Tree{
        int i ,l ,r;
        int mn ,mx ,lazy;
    } tr[N<<2];
    
    struct E{
        int u ,v ,c;
    }e[N];
    
    struct Edge{
        int to ,next;
    }edge[N<<1];
    
    int val[N] ,head[N<<1];
    int fa[N] ,son[N] ,sz[N] ,top[N] ,dfn[N] ,rnk[N] ,dep[N];
    int n ,q ,tot=0 ,cnt = 0; 
    
    // segment tree
    
    
    inline void addedge(int u ,int v){
        edge[++cnt].to = v;
        edge[cnt].next = head[u];
        head[u] = cnt;
        //cout<<u<<" "<<v<<" cnt "<<cnt<<endl;
    }
    
    inline void neg( int i ){
        tr[i].mx *=-1; tr[i].mn *=-1;
        swap( tr[i].mx ,tr[i].mn);
    }
    
    inline void push_up( int i ){
        tr[i].mx = max( tr[li].mx ,tr[ri].mx );
        tr[i].mn = min( tr[li].mn ,tr[ri].mn );
    }
    
    inline void push_down( int i ){
        if( !tr[i].lazy )return;    
        tr[i].lazy = 0;
        // lazy取反 负负得正 
        tr[li].lazy ^= 1 ; tr[ ri].lazy ^= 1;
        
        neg(li); neg(ri);
        return;
    }
    
    void build( int i ,int L ,int R ){
        tr[i].l = L; tr[i].r = R;
        tr[i].lazy = 0;
        if( L== R ){
            tr[i].mn = tr[i].mx = val[ rnk[L] ];
            return;
        }
        int m = (tr[i].l+tr[i].r)>>1;
        build( li ,L ,m );
        build( ri ,m+1 ,R);
        push_up( i );
    }
    
    void negat( int i ,int L ,int R){
        if( tr[i].l == tr[i].r ){
            neg( i );
            return;
        }
        push_down(i);
        
        if( L <= tr[i].l && tr[i].r <= R ){
            tr[i].lazy = 1;
            neg( i );
            return;
        }
        
        int m = (tr[i].l+tr[i].r)>>1;
        if( L <= m )negat( li ,L ,R );
        if( R >  m )negat( ri ,L ,R );
        
        push_up(i);
        return;
    }
    
    void updata( int i ,int p ,int k ){
        
        if( tr[i].l ==p && tr[i].r==p ){
            tr[i].mn = tr[i].mx = k;
            return;
        }
        
        push_down(i);
        
        int m = (tr[i].l+tr[i].r)>>1;
        if( p <= m )updata( li ,p ,k );
        if( p >  m )updata( ri ,p ,k );
        
        push_up(i);
        return;
        
    }
    
    int query(int i ,int L, int R ){
        //cout<<"q l ,r "<<tr[i].l<<" "<<tr[i].r<<" L ,R "<<L << " " <<R <<" " <<rnk[L] <<" "<<rnk[R]<<endl; 
        if( tr[i].l == tr[i].r ){
            return tr[i].mx;
        }
        push_down(i);
        
        int mx = -inf;
        if( L <= tr[i].l && tr[i].r <= R ){
            return tr[i].mx;
        }
        
        int m = (tr[i].l+tr[i].r)>>1;
        if( L <= m )mx =max( mx ,query(li ,L ,R ) );
        if( R >  m )mx =max( mx ,query(ri ,L ,R ) );
    
        return mx;
    }
    // c_tree
    void init( ){
        tot = cnt = 0;
        mem( head ,0 );
        mem( son ,0 );
    }
    
    void dfs1( int u ,int f ,int d ){
        sz[u] = 1;
        fa[u] = f;
        dep[u] = d;
        
        for( int i= head[u] ; i ;i = edge[i].next ){
            int v = edge[i] .to;
            if( v==f )continue;
            dfs1( v ,u ,d+1 );
            sz[u] += sz[v];
            if( sz[ son[u] ] < sz[v] )son[u] = v;
        }
    }
    
    void dfs2( int u ,int tp ){
        top[u] = tp;
        dfn[u] = ++ tot;
        rnk[tot] = u;
        
        if( son[u] )dfs2( son[u] ,tp );
        for( int i =head[u] ;i ;i = edge[i].next ){
            int v = edge[i].to;
            if( v!= fa[u] && v!=son[u] )dfs2(v ,v);    
        }
    }
    
    void c_negate( int x ,int y ){
        int fx = top[x] ,fy = top[y];
        while( fx!=fy ){
            if( dep[fx] < dep[fy] ){
                swap( x ,y ); swap(fx ,fy);
            }
            negat( 1 ,dfn[fx] ,dfn[x] );
            x= fa[fx]; fx = top[x];
        }
        
        if( x==y )return;
        if( dfn[x] > dfn[y] )swap(x ,y);
        negat( 1 ,dfn[son[x]] ,dfn[y] );
    }
    
    
    int c_query(int x ,int y ){
        int mx = -inf;
        int fx = top[x] ,fy = top[y];
        //cout<<x<< " " <<y<<" " <<fx <<" "<<fy<<endl;
        while( fx!=fy ){
            if( dep[fx] < dep[fy] ){
                swap( x ,y ); swap(fx ,fy);
            }
            mx = max(mx ,query( 1 ,dfn[fx] ,dfn[x] ) );
            x= fa[fx]; fx = top[x];
        }
    
        if( x==y )return mx;
        if( dfn[x] > dfn[y] )swap(x ,y);
        mx = max(mx ,query( 1 ,dfn[son[x]] ,dfn[y] ) );
        return mx;
    }
    
    void rev_val( ){
        rep( i ,1 ,n-1 ){
            int u =e[i].u ,v = e[i].v;
            if( dep[v] > dep[u] )swap( e[i].u ,e[i].v );
            val[ e[i].u ] = e[i].c;
        }
    }
    
    int T;
    int main( ){
        //freopen( "out.txt" ,"w" ,stdout );
        scanf( "%d" ,&T );
        while( T-- ){
            init( );
            
            scanf("%d" ,&n);
            rep( i ,1 ,n-1 ){
                scanf("%d%d%d" ,&e[i].u ,&e[i].v ,&e[i].c);
                addedge( e[i].u ,e[i].v );
                addedge( e[i].v ,e[i].u );
                
            }
            
            dfs1( 1 ,0 ,1 );
            dfs2( 1 ,1 );
            rev_val( );
            
            build( 1 ,1 ,n );
            
            char op[15] ;
            int a ,b ,v;
            while( true ){
                cin >>op;
                if(op[0]=='D')break;
                if(op[0]=='C'){
                    scanf("%d%d" ,&a ,&v );
                    updata( 1 ,dfn[ e[a].u ] ,v );
                }
                if( op[0]=='Q' ){
                    scanf("%d%d" ,&a ,&b );
                    printf("%d
    " ,c_query(a ,b));
                }
                if( op[0]=='N' ){
                    scanf("%d%d" ,&a ,&b );
                    c_negate( a, b );
                } 
            }
        }
        return 0;
    }
  • 相关阅读:
    React 高阶组件
    React Context(执行上下文)
    解决背景图片半透明(rgba)兼容性
    js基础复习---数组操作
    js基础复习---字符串操作
    escape()、encodeURI()、encodeURIComponent()区别详解(转)
    form data和request payload的区别(转)
    关于把时间搓转化为时间
    关于js 获取本地当前时间问题
    关于html 头部meta标签。
  • 原文地址:https://www.cnblogs.com/-ifrush/p/11299507.html
Copyright © 2011-2022 走看看