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];

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

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

    改过来后就过了

  • 相关阅读:
    Linux命令应用大词典-第11章 Shell编程
    Kubernetes 学习12 kubernetes 存储卷
    linux dd命令
    Kubernetes 学习11 kubernetes ingress及ingress controller
    Kubernetes 学习10 Service资源
    Kubernetes 学习9 Pod控制器
    Kubernetes 学习8 Pod控制器
    Kubernetes 学习7 Pod控制器应用进阶2
    Kubernetes 学习6 Pod控制器应用进阶
    Kubernetes 学习5 kubernetes资源清单定义入门
  • 原文地址:https://www.cnblogs.com/-ifrush/p/11298343.html
Copyright © 2011-2022 走看看