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可以处理出深度序列,我这里用的是“另一种”深度序列,即时间戳表示的深度序列,用时间戳来代表深度,以及欧拉序列和pos数组,还有in[],out[]数组,表示每个节点DFS进出的时间戳。在DFS时间戳序列上建树状数组,值为每个节点与原来到根节点的距离相比的该变量。要用树状数组需要用一个巧妙的方法转为前缀和问题:在时间戳序列中,如果要更新v的子树,即为更新in[v],out[v],令a = in[v],b=out[v],则可以令A[a] = delta,A[b+1] = -delta。然后更新,就可以用树状数组来查询了。然后每次求两点间距离的时候,结果为固定的dis[u][v]+变动的值(树状数组query求出)。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define N 100007 struct Edge
{
int u,v,w,next;
}G[*N]; int first[N],tot,n,Time,ind,ola[*N],id;
int pos[N],in[*N],out[*N],vis[*N];
int d[*N][],dis[N],c[*N],T[*N],dp[*N]; void RMQ_init()
{
int i,j;
for(i=;i<=id;i++)
d[i][] = dp[i];
for(j=;(<<j)<=id;j++)
{
for(i=;i+(<<j)-<=id;i++)
d[i][j] = min(d[i][j-],d[i+(<<(j-))][j-]);
}
} int RMQ(int l,int r)
{
int k = ;
while((<<(k+)) <= r-l+)
k++;
return min(d[l][k],d[r-(<<k)+][k]);
} void addedge(int u,int v,int w)
{
G[tot].u = u;
G[tot].v = v;
G[tot].w = w;
G[tot].next = first[u];
first[u] = tot++;
} void init()
{
memset(G,,sizeof(G));
memset(first,-,sizeof(first));
memset(c,,sizeof(c));
memset(d,,sizeof(d));
tot = ;
Time = ;
ind = ;
id = ;
} void DFS(int u,int fa)
{
++Time;
int deep = Time;
ola[++ind] = u;
T[Time] = u;
dp[++id] = Time;
in[u] = Time;
for(int i=first[u];i!=-;i=G[i].next)
{
int v = G[i].v;
if(v == fa)
continue;
DFS(v,u);
dp[++id] = deep; //深度序列
ola[++ind] = u; //欧拉序列
}
//if(flag)
//ola[++ind] = u;
out[u] = Time;
} void DFSWG(int u,int w,int fa)
{
dis[u] = w;
for(int i=first[u];i!=-;i=G[i].next)
{
int v = G[i].v;
if(v == fa)
continue;
DFSWG(v,w+G[i].w,u);
}
} void Getpos()
{
memset(vis,,sizeof(vis));
for(int i=;i<=ind;i++)
{
if(!vis[ola[i]])
{
vis[ola[i]] = ;
pos[ola[i]] = i;
}
}
} int LCA(int u,int v)
{
int L = min(pos[u],pos[v]);
int R = max(pos[u],pos[v]);
return T[RMQ(L,R)];
} int lowbit(int x)
{
return x&(-x);
} void update(int k,int num)
{
while(k <= n)
{
c[k] += num;
k += lowbit(k);
}
} int query(int k)
{
int sum = ;
while(k > )
{
sum += c[k];
k -= lowbit(k);
}
return sum;
} int main()
{
int i,j,u,v,w,op,q;
scanf("%d",&n);
{
init();
for(i=;i<n-;i++)
{
scanf("%d%d%d",&u,&v,&w);
addedge(u,v,w);
addedge(v,u,w);
}
scanf("%d",&q);
DFS(,-);
Getpos();
RMQ_init();
DFSWG(,,-); //算出dis
while(q--)
{
scanf("%d%d%d",&op,&u,&v);
if(op == )
{
int lca = LCA(u,v);
printf("%d\n",dis[u]+dis[v]-*dis[lca]+query(in[u])+query(in[v])-*query(in[lca]));
}
else
{
int s = G[*u-].u;
int t = G[*u-].v;
if(pos[s] > pos[t]) //保证s是t的父亲
swap(s,t);
int delta = v - G[*u-].w;
G[*u-].w = G[*u].w = v; //更新权值
update(in[t],delta);
update(out[t]+,-delta);
}
}
}
return ;
}
UESTC 912 树上的距离 --LCA+RMQ+树状数组的更多相关文章
- POJ 2763 (LCA +RMQ+树状数组 || 树链部分) 查询两点距离+修改边权
题意: 知道了一颗有 n 个节点的树和树上每条边的权值,对应两种操作: 0 x 输出 当前节点到 x节点的最短距离,并移动到 x 节点位置 1 x val 把第 x 条边的权值改为 ...
- POJ - 2763 Housewife Wind (树链剖分/ LCA+RMQ+树状数组)
题意:有一棵树,每条边给定初始权值.一个人从s点出发.支持两种操作:修改一条边的权值:求从当前位置到点u的最短路径. 分析:就是在边可以修改的情况下求树上最短路.如果不带修改的话,用RMQ预处理LCA ...
- HDU - 6393 Traffic Network in Numazu (LCA+RMQ+树状数组)
这道题相当于将这两题结合: http://poj.org/problem?id=2763 http://codeforces.com/gym/101808/problem/K 题意:有N各点N条边的带 ...
- HDU6393(LCA + RMQ + 树状数组) n边图,两点最短距离 , 修改边权
这道题的进阶版本 进阶版本 题意: 一个n个点,n条边的图,2中操作,1是将某条边的权值更改,2是询问两点的最短距离. 题解: 由于n个点,n条边,所以是树加一个环,将环上的边随意取出一条,就是1颗树 ...
- Luogu 2680 NOIP 2015 运输计划(树链剖分,LCA,树状数组,树的重心,二分,差分)
Luogu 2680 NOIP 2015 运输计划(树链剖分,LCA,树状数组,树的重心,二分,差分) Description L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之 ...
- hdu5293 lca+dp+树状数组+时间戳
题意是给了 n 个点的树,会有m条链条 链接两个点,计算出他们没有公共点的最大价值, 公共点时这样计算的只要在他们 lca 这条链上有公共点的就说明他们相交 dp[i]为这个点包含的子树所能得到的最 ...
- 【BZOJ】1047: [HAOI2007]理想的正方形(单调队列/~二维rmq+树状数组套树状数组)
http://www.lydsy.com/JudgeOnline/problem.php?id=1047 树状数组套树状数组真心没用QAQ....首先它不能修改..而不修改的可以用单调队列做掉,而且更 ...
- 【BZOJ】1699: [Usaco2007 Jan]Balanced Lineup排队(rmq/树状数组)
http://www.lydsy.com/JudgeOnline/problem.php?id=1699 我是用树状数组做的..rmq的st的话我就不敲了.. #include <cstdio& ...
- BZOJ 2780: [Spoj]8093 Sevenk Love Oimaster( 后缀数组 + 二分 + RMQ + 树状数组 )
全部串起来做SA, 在按字典序排序的后缀中, 包含每个询问串必定是1段连续的区间, 对每个询问串s二分+RMQ求出包含s的区间. 然后就是求区间的不同的数的个数(经典问题), sort queries ...
随机推荐
- Yii路径总结
如果是 // 就会默认去调 protected/views/layouts //代表 绝对路径 其实 就是 绝对和相对的关系 /代表相对路径,如module/user下的layout 用单斜杠的话默认 ...
- Maven创建servlet项目演示(三)
上一节用Maven新建了web项目成功后,本文演示在此基础上应用servlet. 从对tomcat服务器进行配置可的过程中可以知道,tomcat作为servlet容器运行,负责处理客户请求,把请求传送 ...
- 【iOS】Quartz2D截屏
一.简单说明 在程序开发中,有时候需要截取屏幕上的某一块内容,比如捕鱼达人游戏.如图: 完成截屏功能的核心代码:- (void)renderInContext:(CGContextRef)ctx;调用 ...
- 【GOF23设计模式】外观模式
来源:http://www.bjsxt.com/ 一.[GOF23设计模式]_外观模式.公司注册流程.迪米特法则 package com.test.facade; public interface 工 ...
- [CLK Framework] CLK.Settings - 跨平台的参数存取模块
[CLK Framework] CLK.Settings - 跨平台的参数存取模块 问题情景 开发功能模块的时候,常常免不了有一些参数(例如ConnectionString),需要存放在Config檔 ...
- Bit-Coin收入的一分钱
好吧,这是我在Slush's pool上对Bit-coin收入的第一分钱. 回想起来,2013年平安夜开始到今天,将近3个月没日没夜窝在这个矿里挖矿 从最开始的集成显卡挖,买了显卡挖,加了显卡挖,使用 ...
- Eclipse下link方式安装插件
一.eclipse安装位置和存放文件位置 eclipse安装位置:D:\ProgramFile\eclipse存放文件:D:\mydep 二.下载插件 这里下载的是PropertiesEditor解压 ...
- IOS CALayer(一)
对于一个app的好坏,我们首要判断的便是app的界面,而界面的建立则是在图形的处理基础上的,说到图形处理又不得不提及Quartz2D,CALayer. 在iOS系统中,你能看得见摸得着的东西基本上都是 ...
- iOS开发笔记1:ToDoList、相册、地图应用及新浪微博
前段时间做了一些小东西,一些关键点记录总结如下 1.ToDoList 主要是使用UITableView以及NSUserDefaults完成任务管理,可新建.编辑及删除任务. 因为是Demo性质,所以利 ...
- genymotion虚拟机启动失败
错误提示如下: Make sure that you have installed it correctly before starting Genymotion. 解决方法(重启VirtualBox ...