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\n" ,c_query(a ,b));
            }
            if( op[0]=='N' ){
                scanf("%d%d" ,&a ,&b );
                c_negate( a, b );
            } 
        }
    }
    return 0;
}
posted @ 2019-08-04 20:19  易如鱼  阅读(247)  评论(0编辑  收藏  举报