8.4 poj 2763 Housewife Wind (樹鏈剖分邊權處理


題意:

給定一棵含n個結點的樹和樹的邊權,共有q次操作,分為兩種

0 c :求從位置s到c的距離,然后s變成c

1 a b:把第a條邊的權值變為b

 

邊權處理一般有兩種方案:

1.化邊為點

即將所有的n-1條邊上都增加一個節點,點權即邊權,再有2n-1個節點的新樹上進行點權的樹鏈剖分即可

(一般不用

 

2.邊附點

將邊權附加在它深度更深的端點上(dep[v] > dep[u] ),處理x,y之間的路徑時其他操作和之前一樣,只是最后不處理x,y的lca的點權(因為它點權所代表的的邊權不在這條路徑上):

最后一步是:ans += query( 1 ,dfn[son[x]] ,dfn[y] ); 或 ans += query( 1 ,dfn[x]+1 ,dfn[y] );

注意當x==y時x,y本沈就是lca,直接不進行操作return就行

 

這個題寫了1天也沒過orz

先是wa: 問題就是上面說到的x==y時的處理沒有注意

然后就一直tle,問題不明 ,線段樹改成了結構體寫法還是tle

貼一下代碼,以后可能會發現錯誤在哪:

//樹鏈剖分 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 lson  pos<<1 ,l ,m
#define rson  pos<<1|1 ,m+1 ,r
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 Edge{
    int to ,val ,next;
}edge[N<<1];

struct E{
    int u ,v ,c;
}e[N<<1];

struct Tree{
    int left ,right;
    int t ,lazy;
}tree[N<<2];

int val[N] ,tr[N<<2];
int head[N];
int dep[N] ,dfn[N] ,son[N] ,fa[N];
int rnk[N] ,sz[N] ,top[N];
int cnt = 0,tot = 0 ,n ,q ,s ;


void init( ){
    cnt = tot =0;
    dep[1] = val[1] = 0;
    mem( head ,0 );
    mem( son , 0 );
    
}

void add_edge( int u ,int v ){
    edge[++cnt].to = v;
    edge[cnt].next = head[u];
    head[u] = cnt;
}

// sgement tree

void push_up( int pos ){
    tree[pos].t = tree[pos<<1].t + tree[pos<<1|1].t;
}

void build( int pos , int l ,int r ){
    
        tree[pos].left = l;
        tree[pos].right= r;
    if( l==r ){    
        tree[pos].t = val[ rnk[l] ];
        return;
    }
    int m = (l+r)>>1;
    build( lson );
    build( rson );
    push_up( pos ); 
}


void updata( int pos ,int p ,int v ){
    //cout<<tree[pos].left<<" "<<tree[pos].right<<endl;
    if( tree[pos].left == p && tree[pos].right ==p ){
        tree[pos].t = v; return;
    }
    
    int m = (tree[pos].left+tree[pos].right)>>1;
    if( p<=m)updata( pos<<1 ,p ,v );
    else updata( pos<<1|1 ,p ,v );
    push_up( pos );
}

int query( int pos ,int l ,int r  ){
    if( l <= tree[pos].left && tree[pos].right <= r){
        return tree[pos].t;
    }
    int ans = 0;
    int m = ( tree[pos].left+tree[pos].right )>>1;
    if( m >= l )ans += query( pos<<1 ,l ,r );
    if( m < r ) ans += query( pos<<1|1 ,l ,r );
    return ans;
}

// tree - chain 
// dfs 1-- dep ,sz ,fa ,son
void dfs1( int u ,int f ){
    sz[u] = 1;
    for( int i = head[u]; i ;i = edge[i].next ){
        int v = edge[i].to;
        if( v == f )continue;
        dep[v] = dep[u] + 1;
        fa[v] = u;
        dfs1( v ,u );
        sz[u] += sz[v];
        if( sz[v] >sz[ son[u] ] )son[u] = v;
    }
}

void dfs2( int u ,int t ){
    dfn[u] = ++tot;
    top[u] = t;
    rnk[tot] = u;
    if( son[u] )dfs2( son[u] ,t );
    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);
    }
}

int LCA( int x ,int y ){
    int fx = top[x] ,fy = top[y];
    while( fx != fy ){
        if( dep[x] < dep[y] )swap(x ,y) ,swap( fx ,fy );
        x= fa[fx] ,fx = top[x];
    }
    return dep[x] < dep[y] ? x : y ;
}

/*void c_updata( int x ,int y ,int v ){
    int fx = top[x] ,fy = top[y];
    while( fx != fy ){
        if( dep[fx] < dep[fy] )swap(x ,y) ,swap(fx ,fy);
        updata( 1 ,1 ,n ,dfn[fx] ,dfn[x] ,v);
        x = f[x] ,fx = top[x];
    }
    if( dfn[x] > dfn[y] )swap( x ,y );
    updata( 1 ,1 ,n ,dfn[x] ,dfn[y] ,v);
}
*/
int c_query( int x ,int y ){
    int fx = top[x] ,fy = top[y];
    int ans = 0;
    while( fx != fy ){
        if( dep[fx] < dep[fy] )swap(x ,y) ,swap(fx ,fy);
        ans += query( 1 ,dfn[fx] ,dfn[x] );
        x = fa[x] ,fx = top[x];
    }
    if( x==y )return ans;
    if( dfn[x] > dfn[y] )swap( x ,y );
    //cout<<x<<" son2 "<<son[x]<<endl;
    // x = son[x]; 致死錯誤 
    if(dfn[x] != dfn[y])ans += query( 1 ,dfn[son[x]] ,dfn[y] );
    return ans ;
}

void rev_edge( ){
    rep( i ,1 ,n-1 ){
        if( dep[e[i].v] > dep[e[i].u] )val[e[i].v] = e[i].c;
        else val[e[i].u] = e[i].c;
        //cout<<" rev_edge "<<e[i].u<<" "<<val[e[i].u]<<" "<<e[i].v<<" "<<val[e[i].v]<<endl;
        } 
}

int main( ){
    scanf( "%d%d%d" ,&n ,&q ,&s ) ;
    //init();
    rep( i ,1 ,n-1 ){
       scanf("%d%d%d" ,&e[i].v ,&e[i].u ,&e[i].c);
       add_edge( e[i].u ,e[i].v);
       add_edge( e[i].v ,e[i].u);
    }
    dfs1( 1 ,1 );
    dfs2( 1 ,1 );
    rev_edge( );
    build( 1 ,1 ,n );
    int op ,l ,r ,z;
    while( q-- ){
        scanf("%d" ,&op );
        if( op ){
            scanf("%d%d",&l ,&z);
            if( dep[e[l].v] > dep[e[l].u] )l = e[l].v;
            else l = e[l].u;
            updata( 1 ,dfn[l] ,z );
        }
        else{
            scanf("%d" ,&l );
            printf( "%d\n" ,c_query( s ,l) );
            s = l;
        }
    }

    return 0;
} 

 

別人可以過的代碼:https://www.cnblogs.com/yaoyueduzhen/p/5311230.html

我覺得就邊權附到節點那個過程我們有些許差異,其他地方基本一樣啊,為什么我寫的過不了呢?

sad,陷入了迷惑與巨大的沮喪中

 

找到錯誤了!

在函數c_query里:

int c_query( int x ,int y ){
    int fx = top[x] ,fy = top[y];
    int ans = 0;
    while( fx != fy ){
        if( dep[fx] < dep[fy] )swap(x ,y) ,swap(fx ,fy);
        ans += query( 1 ,dfn[fx] ,dfn[x] );
        x = fa[x] ,fx = top[x];
    }
    if( x==y )return ans;
    if( dfn[x] > dfn[y] )swap( x ,y );
    //cout<<x<<" son2 "<<son[x]<<endl;
    // x = son[x]; 致死錯誤 
    if(dfn[x] != dfn[y])ans += query( 1 ,dfn[son[x]] ,dfn[y] );
    return ans ;
}

這一句:

 x = fa[x] ,fx = top[x];

 

應為:

 x = fa[fx] ,fx = top[x];

這里前面思路是對的,就是手殘,下意識,肌肉記憶

事實上,代碼我后來又重寫了兩遍  ,這里依然是寫錯的,人的大腦真的很神奇

改過來后就過了

 


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com