Network

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 847    Accepted Submission(s): 347

Problem Description
The
ALPC company is now working on his own network system, which is
connecting all N ALPC department. To economize on spending, the backbone
network has only one router for each department, and N-1 optical fiber
in total to connect all routers.
The usual way to measure connecting
speed is lag, or network latency, referring the time taken for a sent
packet of data to be received at the other end.
Now the network is on
trial, and new photonic crystal fibers designed by ALPC42 is trying
out, the lag on fibers can be ignored. That means, lag happened when
message transport through the router. ALPC42 is trying to change routers
to make the network faster, now he want to know that, which router, in
any exactly time, between any pair of nodes, the K-th high latency is.
He needs your help.
 
Input
There are only one test case in input file.
Your
program is able to get the information of N routers and N-1 fiber
connections from input, and Q questions for two condition: 1. For some
reason, the latency of one router changed. 2. Querying the K-th longest
lag router between two routers.
For each data case, two integers N and Q for first line. 0<=N<=80000, 0<=Q<=30000.
Then n integers in second line refer to the latency of each router in the very beginning.
Then N-1 lines followed, contains two integers x and y for each, telling there is a fiber connect router x and router y.
Then
q lines followed to describe questions, three numbers k, a, b for each
line. If k=0, Telling the latency of router a, Ta changed to b; if
k>0, asking the latency of the k-th longest lag router between a and b
(include router a and b). 0<=b<100000000.
A blank line follows after each case.
 
Output
For
each question k>0, print a line to answer the latency time. Once
there are less than k routers in the way, print "invalid request!"
instead.
 
Sample Input
5 5
5 1 2 3 4
3 1
2 1
4 3
5 3
2 4 5
0 1 2
2 2 3
2 1 4
3 3 5
 
Sample Output
3
2
2
invalid request!
 
题意:给出n个点,m条询问,依次输入n个点都有权值,以及n-1条边,接下来m条询问每次输入 k a b如果 k=0 ,则更新a点的权值为b,如果k>0,则输出a-b这条路径上权值第K大的点,如果没有第K大点,输出invalid request!
今天做这个题,正好借这个题总结一下LCA的在线算法。
aaarticlea/png;base64,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" alt="" />
上图为测试用例:
LCA的在线算法,先要对此树进行预处理(为以后的RMQ做准备),即进行深搜。
我们设立三个数组:ver,first,deep ver数组保存树的前序遍历结点的结果,first保存结点第一次出现的位置,deep保存每个节点出现的深度
对此树进行先序遍历:
ver: 1 2 1 3 4 3 5 3 1
deep:1 2 1 2 3 2 3 2 1
first:1 2 4 5 7
从这里可以知道 ver和deep都要开两倍大小。
然后如果查询结点 2 5,先找到2以及5第一次出现的位置,first[2] = 2,first[5] = 7
那么2和5的最近公共祖先必定在ver[2]-ver[7]区间中。那么接下来,我们只要拿出这段区间内深度最小的点,那么这个点就肯定是2 5的最近公共祖先了
所以这里找区间最小值我们就可以利用RMQ算法了(这里RMQ的数组保存的是下标,因为deep和ver数组是通过下标联系起来的)。找到了2 1 2 3 2 3中
深度最小的是deep[3],对应ver中的ver[3]=1,所以2 和 5的最近公共祖先是1
了解了过程,代码也就能够写出来了。
然后关于这题:我们要找a - b中的第K大点,那么我们记录一个父亲数组,u->lca,v->lca反着找就OK。
/*
5 5
5 1 2 3 4 3 1 2 1 4 3 5 3
2 4 5
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include <string.h>
#include <math.h>
#define N 80005
using namespace std; struct Edge{
int u,v,next;
}edge[*N];
int head[N];
int deep[*N];
int vis[N];
int first[N];
int ver[*N];
int father[N];
int dp[*N][];
int value[N];
int path[N];
int tot; void add_edge(int u,int v,int &k){ ///Á´Ê½Ç°ÏòÐÇ
edge[k].u = u,edge[k].v = v;
edge[k].next = head[u];head[u] = k++;
}
void dfs(int u,int dep,int pre){
vis[u]=true,ver[++tot]=u,first[u]=tot,deep[tot]=dep,father[u]=pre;
for(int k=head[u];k!=-;k=edge[k].next){
if(!vis[edge[k].v]){
dfs(edge[k].v,dep+,u);
ver[++tot] = u,deep[tot]=dep;
}
}
}
int MIN(int i,int j){
if(deep[i]<deep[j]) return i;
return j;
}
void init_RMQ(int n){
for(int i=;i<=n;i++) dp[i][]=i;
for(int j=;(<<j)<=n;j++){
for(int i=;i+(<<j)-<=n;i++){
dp[i][j] = MIN(dp[i][j-],dp[i+(<<(j-))][j-]);
}
}
}
int RMQ(int L,int R){
int k = (int)(log(R-L+1.0)/log(2.0));
int a = dp[L][k];
int b = dp[R-(<<k)+][k];
return MIN(a,b);
}
int LCA(int a,int b){
int x = first[a],y = first[b];
//printf("%d %d\n",deep[x],deep[y]);
if(x>y) swap(x,y);
//printf("RMQ(x,y): %d\n",RMQ(x,y));
return ver[RMQ(x,y)];
}
int cmp(int a,int b){
return a>b;
}
void solve(int k,int u,int v){
int lca = LCA(u,v);
tot=;
while(u!=lca){
path[tot++] = value[u];
u = father[u];
}
while(v!=lca){
path[tot++] = value[v];
v = father[v];
}
//printf("lca = %d\n",lca);
path[tot++] = value[lca];
//printf("path[tot-1] = %d\n",path[tot-1]);
if(k>tot){
printf("invalid request!\n");
return;
}
sort(path,path+tot,cmp);
//for(int i=0;i<tot;i++) printf("%d ",path[i]);
printf("%d\n",path[k-]);
}
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF){
memset(head,-,sizeof(head));
memset(father,-,sizeof(father));
for(int i=;i<=n;i++){
scanf("%d",&value[i]);
}
tot = ;
for(int i=;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
add_edge(u,v,tot);
add_edge(v,u,tot);
}
tot = ;
dfs(,,-);
init_RMQ(*n-);
while(m--){
int k,a,b;
scanf("%d%d%d",&k,&a,&b);
if(k==){
value[a]=b;
}else{
solve(k,a,b);
}
}
}
return ;
}
 

hdu 3078(LCA的在线算法)的更多相关文章

  1. LCA(倍增在线算法) codevs 2370 小机房的树

    codevs 2370 小机房的树 时间限制: 1 s  空间限制: 256000 KB  题目等级 : 钻石 Diamond 题目描述 Description 小机房有棵焕狗种的树,树上有N个节点, ...

  2. HDU 3078 (LCA+树链第K大)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3078 题目大意:定点修改.查询树中任意一条树链上,第K大值. 解题思路: 先用离线Tarjan把每个 ...

  3. HDU 3078 LCA转RMQ

    题意: n个点 m个询问 下面n个数字表示点权值 n-1行给定一棵树 m个询问 k u v k为0时把u点权值改为v 或者问 u-v的路径上 第k大的数 思路: LCA转RMQ求出 LCA(u,v) ...

  4. LCA(最近公共祖先)——dfs+ST 在线算法

    一.前人种树 博客:浅谈LCA的在线算法ST表 二.沙场练兵 题目:POJ 1330 Nearest Common Ancestors 题解博客:http://www.cnblogs.com/Miss ...

  5. LCA最近公共祖先 ST+RMQ在线算法

    对于一类题目,是一棵树或者森林,有多次查询,求2点间的距离,可以用LCA来解决.     这一类的问题有2中解决方法.第一种就是tarjan的离线算法,还有一中是基于ST算法的在线算法.复杂度都是O( ...

  6. LCA在线算法ST算法

    求LCA(近期公共祖先)的算法有好多,按在线和离线分为在线算法和离线算法. 离线算法有基于搜索的Tarjan算法较优,而在线算法则是基于dp的ST算法较优. 首先说一下ST算法. 这个算法是基于RMQ ...

  7. LCA在线算法详解

    LCA(最近公共祖先)的求法有多种,这里先介绍第一种:在线算法. 声明一下:下面的内容参考了http://www.cnblogs.com/scau20110726/archive/2013/05/26 ...

  8. POJ 1330 Nearest Common Ancestors (LCA,倍增算法,在线算法)

    /* *********************************************** Author :kuangbin Created Time :2013-9-5 9:45:17 F ...

  9. POJ 1330 Nearest Common Ancestors (LCA,dfs+ST在线算法)

    Nearest Common Ancestors Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 14902   Accept ...

随机推荐

  1. apache和IIS共享80端口解决办法

    第一步:把iis所发布的网站默认端口由80改为8080:第二步:修改apache的httpd.conf配置文件. 首先,要让apache支持转发也就是做iis的代理那么就要先启 用apache的代理模 ...

  2. MyBatis代码生成工具mybatis-generator在Myeclipse10中的使用

    一.在MyEclipse安装目录下新建myPlugin目录,如下图所示: 二.将 mybatis.zip 里面的文件放在MyEclipse的dropins目录下,如下图所示: 三.在Myeclipse ...

  3. selenium-控制浏览器操作

    from selenium import webdriver driver = webdriver.Chrome() #打开浏览器 driver.get(urlname) #控制浏览器窗口大小 dri ...

  4. Spring------mysql读写分离

    1. 为什么要进行读写分离 大量的JavaWeb应用做的是IO密集型任务, 数据库的压力较大, 需要分流 大量的应用场景, 是读多写少, 数据库读取的压力更大 一个很自然的思路是使用一主多从的数据库集 ...

  5. 从samsung提供内核进行移植

    1.尝试编译分析结果 配置编译下载尝试 (1)检查Makefile中ARCH和CROSS_COMPILE(2)make xx_defconfig(3)make menuconfig(4)make -j ...

  6. 旋转 3d

    建议chorme浏览器浏览,有样式兼容性问题. 图片可以根据自己本地路径设置路径,js库引用jquery. 写的不好,多多建议,谢谢大家. <html onselectstart="r ...

  7. http学习 - 缓存

    对缓存的理解更加深刻,缓存有一个过期时间,现在用的比较多的是 max-age,以前使用 expirt之类的, 然后就是需要向服务器验证是否是最新的,如果不是最新的则需要更新.

  8. sublime text 快速编码技巧 GIT图

    网上到处都云云sublime有多好.用了一年多的时间,受益匪浅,减少了很多重复性的劳动. 特别是: 1.灵活强大的多行编辑功能: 2.快速查找文件 ctrl + p; 3.正则查找 + 多行编辑; 4 ...

  9. [LA3135]node形式的优先队列

    n个触发器,每个触发器每period秒就产生一个编号为qnum的事件,求前k个事件. n<=1000  k<=10000 node形式的优先队列 主要在于重载小于号,确定优先顺序. #in ...

  10. 【点分治练习题·不虚就是要AK】点分治

    不虚就是要AK(czyak.c/.cpp/.pas)  2s 128M  by zhb czy很火.因为又有人说他虚了.为了证明他不虚,他决定要在这次比赛AK. 现在他正在和别人玩一个游戏:在一棵树上 ...