zoukankan      html  css  js  c++  java
  • 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
    " ,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];

    这里前面思路是对的,就是手残,下意识,肌肉记忆

    事实上,代码我后来又重写了两遍  ,这里依然是写错的,人的大脑真的很神奇

    改过来后就过了

  • 相关阅读:
    Ubuntu 13.10 x64 安装 Eclipse Android SDK Java开发IDE
    域名 TTL 查询
    mysql 常用设置:字符集编码、自动完成(自动提示)、监听外网ip
    PHP 设置:timezone、error_log
    数字发行:电子书、电影、游戏、音乐
    细节:php array会把string key自动转成int吗?
    REST URI设计:版本号放在http header中,rewrite配置
    Linux时区设置
    Linux添加sudo用户
    php curl常见错误:SSL错误、bool(false)
  • 原文地址:https://www.cnblogs.com/-ifrush/p/11298343.html
Copyright © 2011-2022 走看看