HDU - 6393 Traffic Network in Numazu (LCA+RMQ+树状数组)

这道题相当于将这两题结合:

  http://poj.org/problem?id=2763

  http://codeforces.com/gym/101808/problem/K

题意:有N各点N条边的带权无向图(相当于一棵树多了一条边),两种操作:修改一条边的权值;求两点间的最短路径。

分析:将任意一条边取出来,其余n-1条边可以结合LCA解最短路。询问时,比较通过取出的边和仅通过树上的边的路径的大小,最小值就是两点的最短路径。

树状数组差分维护点到根节点的距离,根据dfs序来记录需要维护的范围。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define maxn 100005
typedef long long LL;
struct Edge{
    int to,next,id;
}edge[maxn<<1];

int n,a[maxn],head[maxn],dep[maxn<<1],cnt,pos[maxn],dfs_seq[maxn<<1],dfn,f[maxn<<1][20];
int L[maxn],R[maxn],dfs_clock,G[maxn];
LL W[maxn],C[maxn];

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

inline int lowbit(int x){return (x)&(-x);}

void init(){
    memset(head,-1,sizeof(head));
    memset(pos,-1,sizeof(pos));
    memset(C,0,sizeof(C));
    cnt=dfn=0;
    dfs_clock=0;
}

void dfs(int u,int deep)
{
    dfs_seq[dfn]=u,dep[dfn]=deep,pos[u]=dfn++;
    L[u]=++dfs_clock;
    for(int i=head[u];~i;i=edge[i].next){
        int v=edge[i].to;
        if(pos[v]==-1){
            G[edge[i].id]=v;                //important
            dfs(v,deep+1);
            dfs_seq[dfn]=u,dep[dfn++]=deep;
        }
    }
    R[u]=dfs_clock;
}

void init_RMQ(int n)
{
    for(int i=1;i<=n;++i) f[i][0]=i;
    for(int j=1;(1<<j)<=n;++j)
        for(int i=1;i+(1<<j)-1<=n;++i){
            if(dep[f[i][j-1]]<dep[f[i+(1<<(j-1))][j-1]]) f[i][j]=f[i][j-1];
            else f[i][j]=f[i+(1<<(j-1))][j-1];
        }
}

inline int RMQ(int L,int R)
{
    int k=0;
    while(1<<(k+1)<=R-L+1) ++k;
    if(dep[f[L][k]]<dep[f[R-(1<<k)+1][k]]) return f[L][k];
    return f[R-(1<<k)+1][k];
}

inline int lca(int u,int v)
{
    if(pos[u]>pos[v]) return dfs_seq[RMQ(pos[v],pos[u])];
    return dfs_seq[RMQ(pos[u],pos[v])];
}

inline void update(int i,LL x)
{
    for(;i<=n;i+=lowbit(i)) C[i]+=x;
}

inline LL sum(int i)
{
    LL s=0;
    for(;i>0;i-=lowbit(i)) s+=C[i];
    return s;
}

inline LL dist(int u,int v)
{
    return sum(L[u])+sum(L[v])-2*sum(L[lca(u,v)]);
}

int main()
{
    #ifndef ONLINE_JUDGE
            freopen("in.txt","r",stdin);
            freopen("out.txt","w",stdout);
    #endif
    int i,u,v,k,q,s,T;
    LL w;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&q);
        init();
        for(i=1;i<=n-1;++i){
            scanf("%d%d%lld",&u,&v,&w);
            add(u,v,i);
            add(v,u,i);
            W[i]=w;
        }
        dfs(1,0);
        init_RMQ(dfn-1);
        int X,Y; LL Z;
        scanf("%d%d%lld",&X,&Y,&Z);               //第n条边
        W[n] = Z;
        for(i=1;i<n;++i){
            update(L[G[i]],W[i]);
            update(R[G[i]]+1,-W[i]);
        }

        while(q--){
            scanf("%d",&k);
            if(k==0){
                scanf("%d%lld",&u,&w);
                if(u==n)
                    W[n] = w;
                else{
                    update(L[G[u]],w-W[u]);
                    update(R[G[u]]+1,-w+W[u]);
                    W[u]=w;
                }
            }
            else{
                scanf("%d%d",&u,&v);
                LL ans=dist(u,v);
                ans=min(ans,dist(u,X)+dist(v,X));
                ans=min(ans,dist(u,Y)+dist(v,Y));
                ans=min(ans,dist(u,X)+dist(v,Y)+Z);
                ans=min(ans,dist(u,Y)+dist(v,X)+Z);
                printf("%lld\n",ans);
            }
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/xiuwenli/p/9470162.html

时间: 2024-11-08 11:20:07

HDU - 6393 Traffic Network in Numazu (LCA+RMQ+树状数组)的相关文章

UESTC 912 树上的距离 --LCA+RMQ+树状数组

1.易知,树上两点的距离dis[u][v] = D[u]+D[v]-2*D[lca(u,v)] (D为节点到根节点的距离) 2.某条边<u,v>权值一旦改变,将会影响所有以v为根的子树上的节点到根节点的距离,很明显,DFS一遍后以v为根的子树在DFS序列中是连续的一段,及转化为区间更新问题,可以用树状数组. 做法:先把求LCA解决,LCA可以转化为RMQ问题,可参见:LCA转RMQ, 即转化为LCA(T,u,v) = RMQ(B,pos[u],pos[v]),其中B为深度序列.预先DFS可以处

HDU - 6393 Traffic Network in Numazu(树链剖分+基环树)

http://acm.hdu.edu.cn/showproblem.php?pid=6393 题意 给n个点和n条边的图,有两种操作,一种修改边权,另一种查询u到v的最短路. 分析 n个点和n条边,实际上是一棵树+一个环,如果仅仅是一棵树,那么这题就是树链剖分的模板题了. 对于环来说,可以考虑先把环中一条边提取出来,然后树链剖分,修改时用线段树,单点修改和区间求和. 查询时就考虑三种情况,u走树上到v,从u经过提取出来的边再到v(两种),取最小值. 至于取出环上一条边,用并查集搞搞. #incl

hdu 1556:Color the ball(第二类树状数组 —— 区间更新,点求和)

Color the ball Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 8984    Accepted Submission(s): 4594 Problem Description N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的“小飞鸽"牌电动车从气球

HDU 3333 Turing Tree (离散化+离线处理+树状数组)

Problem Description After inventing Turing Tree, 3xian always felt boring when solving problems about intervals, because Turing Tree could easily have the solution. As well, wily 3xian made lots of new problems about intervals. So, today, this sick t

HDU 1166 敌兵布阵 (我的树状数组加线段树点修改模板)

思路:本题因为是点修改,所以我们可以用线段树或者是树状数组了.线段树的基本操作我在我的代码中会具体体现,关键是要理解下面这幅图,具体的思想大家可以去看看其他的资料 线段树AC代码: #include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std; #define N 50005 int num

RMQ &amp;&amp; 树状数组 (初学)

先复习一下今天刚学的RMQ算法知识; RMQ算法(Range Minimum Query) :1.算法思想 求静态范围最值问题,适合于静态连续区间查询. A[ i ] [ j ] 的值代表的是原数组中以 i 开始的连续 (1<< j)个数的最值. 2.代码 <pre name="code" class="cpp">//2.1 预处理代码 for(int j = 1 ; j != 20 ; ++j ) // 代表区间大小 for(int i =

HDU 2227 Find the nondecreasing subsequences dp思想 + 树状数组

http://acm.hdu.edu.cn/showproblem.php?pid=2227 用dp[i]表示以第i个数为结尾的nondecreasing串有多少个. 那么对于每个a[i] 要去找 <= a[i]的数字那些位置,加上他们的dp值即可. 可以用树状数组维护 #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algori

hdu5293 lca+dp+树状数组+时间戳

题意是给了 n 个点的树,会有m条链条 链接两个点,计算出他们没有公共点的最大价值,  公共点时这样计算的只要在他们 lca 这条链上有公共点的就说明他们相交 dp[i]为这个点包含的子树所能得到的最大价值 sum[i]表示这个点没有选择经过i这个点链条的总价值 两种选择 这个点没有被选择 dp[i]=sum[i]=sigma(dp[k])k为i的子树 选择了某个链 假设这条链 为(tyuijk) 那么dp[i]=(sum[i]-dp[u]-dp[j])+(sum[j]-dp[k])+dp[k]

BZOJ 2780: [Spoj]8093 Sevenk Love Oimaster( 后缀数组 + 二分 + RMQ + 树状数组 )

全部串起来做SA, 在按字典序排序的后缀中, 包含每个询问串必定是1段连续的区间, 对每个询问串s二分+RMQ求出包含s的区间. 然后就是求区间的不同的数的个数(经典问题), sort queries + BIT 就行了.时间复杂度O(N log N). 速度垫底了QAQ 你们都会SAM.... ---------------------------------------------------------------------- #include<cmath> #include<c