LCA【SP913】Qtree - Query on a tree II
Description
给定一棵n个点的树,边具有边权。要求作以下操作:
DIST a b 询问点a至点b路径上的边权之和
KTH a b k 询问点a至点b有向路径上的第k个点的编号
有多组测试数据,每组数据以DONE结尾。
Input
第一组数据包含一个整数\(T\),代表有\(T\)组测试数据。\(1\leq T \leq 25\)
对每一组测试数据:
- 第一行一个整数\(N(n \leq 10000)\)
- 接下来有\(N-1\)行,每一行描述树上的一条边\(a,b,c( c\leq 100000)\)
- 接下来几行操作包括\(DIST \ a \ b\),\(KTH \ a \ b \ k\)
- 以\(DONE\)结尾
Output
对于每一个\(DIST\)和\(KTH\)询问输出一行.
很明显,LCA,但是难点就在于如何求出\(KTH\)对于的答案.
首先会存在两种情况
一. \(k \leq depth[x]-depth[lca_{x,y}]+1\)
很明显,这时第\(k\)个点必然在于\(x->lca_{x,y}\)的路径上,我们只需要知道其深度即可倍增求取.
可求其深度为\(depth[x]-k+1\)
二. \(k > depth[x]-depth[lca_{x,y}]+1\)
这时,第\(k\)个点必然存在于\(y->lca_{x,y}\)的路径上,但是如何求其深度却是一个问题.
先设\(ans\)为第\(k\)个点的深度.
我们可以得到的信息是\(k\)必须要在\(y->lca_{x,y}\),
所以新的深度至少必须为\(k-(depth[x]-depth[lca_{x,y}]+1)\)
但是由于我们的\(lca_{x,y}\)不一定为\(1\)(这里我以\(1\)为根)
所以原式子还需要加上一个\(depth[lca_{x,y}]\)。
因此可以得到这样一个式子
\]
知道深度之后,直接倍增跳即可.
代码
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
#define clear(a) memset(a,0,sizeof a)
#define N 10008
#define R register
using namespace std;
inline void in(int &x)
{
int f=1;x=0;char s=getchar();
while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
while(isdigit(s)){x=x*10+s-'0';s=getchar();}
x*=f;
}
int T;
int n,head[N],tot;
struct cod{int u,v,w;}edge[N<<2];
inline void add(int x,int y,int z)
{
edge[++tot].u=head[x];
edge[tot].v=y;
edge[tot].w=z;
head[x]=tot;
}
int depth[N],f[N][21],dis[N];
void dfs(int u,int fa,int dist)
{
f[u][0]=fa;dis[u]=dis[fa]+dist;depth[u]=depth[fa]+1;
for(R int i=1;(1<<i)<=depth[u];i++)
f[u][i]=f[f[u][i-1]][i-1];
for(R int i=head[u];i;i=edge[i].u)
{
if(edge[i].v==fa)continue;
dfs(edge[i].v,u,edge[i].w);
}
}
inline int lca(int x,int y)
{
if(depth[x]>depth[y])swap(x,y);
for(R int i=17;i>=0;i--)
if(depth[x]+(1<<i)<=depth[y])
y=f[y][i];
if(x==y)return y;
for(R int i=17;i>=0;i--)
{
if(f[x][i]==f[y][i])continue;
x=f[x][i],y=f[y][i];
}
return f[x][0];
}
char s[108];
inline int query(int x,int y,int k)
{
R int la=lca(x,y);
if(depth[x]-depth[la]+1>=k)
{
R int ans=depth[x]-k+1;
for(R int i=17;i>=0;i--)
{
if(depth[x]-ans>=(1<<i))
x=f[x][i];
}
return x;
}
else
{
R int ans=depth[la]*2+k-depth[x]-1;
for(R int i=17;i>=0;i--)
if((1<<i)<=depth[y]-ans)
y=f[y][i];
return y;
}
}
int main()
{
in(T);
for(;T;T--)
{
in(n);
tot=0;clear(head),clear(dis),clear(f);clear(depth);
for(R int i=1,x,y,z;i<n;i++)
{
in(x),in(y),in(z);
add(x,y,z);add(y,x,z);
}
dfs(1,0,0);
for(R int x,y,la,k;;)
{
scanf("%s",s+1);
if(s[2]=='O')break;
if(s[2]=='I')
{
in(x),in(y);
la=lca(x,y);
printf("%d\n",dis[x]+dis[y]-2*dis[la]);
}
else
{
in(x),in(y),in(k);
printf("%d\n",query(x,y,k));
}
}
}
}
LCA【SP913】Qtree - Query on a tree II的更多相关文章
- 【BZOJ1803】Spoj1487 Query on a tree III 主席树+DFS序
[BZOJ1803]Spoj1487 Query on a tree III Description You are given a node-labeled rooted tree with n n ...
- 【BZOJ2589】[SPOJ10707]Count on a tree II
[BZOJ2589][SPOJ10707]Count on a tree II 题面 bzoj 题解 这题如果不强制在线就是一个很\(sb\)的莫队了,但是它强制在线啊\(qaq\) 所以我们就用到了 ...
- 【SPOJ10707】 COT2 Count on a tree II
SPOJ10707 COT2 Count on a tree II Solution 我会强制在线版本! Solution戳这里 代码实现 #include<stdio.h> #inclu ...
- 【SPOJ QTREE2】QTREE2 - Query on a tree II(LCA)
You are given a tree (an undirected acyclic connected graph) with N nodes, and edges numbered 1, 2, ...
- 【SPOJ】375. Query on a tree(树链剖分)
http://www.spoj.com/problems/QTREE/ 这是按边分类的. 调试调到吐,对拍都查不出来,后来改了下造数据的,拍出来了.囧啊啊啊啊啊啊 时间都花在调试上了,打hld只用了半 ...
- 树链剖分【p4116】Qtree3 - Query on a tree
Description 给出N个点的一棵树(N-1条边),节点有白有黑,初始全为白 有两种操作: 0 i : 改变某点的颜色(原来是黑的变白,原来是白的变黑) 1 v : 询问1到v的路径上的第一个黑 ...
- 【bzoj1803】Spoj1487 Query on a tree III DFS序+主席树
题目描述 You are given a node-labeled rooted tree with n nodes. Define the query (x, k): Find the node w ...
- 【SPOJ10707】COT2 - Count on a tree II
题目大意:给定一棵 N 个节点的无根树,每个节点有一个颜色.现有 M 个询问,每次询问一条树链上的不同颜色数. 题解:学会了树上莫队. 树上莫队是将节点按照欧拉序进行排序,将树上问题转化成序列上的问题 ...
- 【树上莫队】【SP10707】 COT2 - Count on a tree II
Description 给定一棵 \(n\) 个点的树,每个节点有一个权值,\(m\) 次询问,每次查询两点间路径上有多少不同的权值 Input 第一行是 \(n\) 和 \(m\) 第二行是 \(n ...
随机推荐
- Hadoop上配置Hbase数据库
已有环境: 1. Ubuntu:14.04.2 2.jdk: 1.8.0_45 3.hadoop:2.6.0 4.hBase:1.0.0 详细过程: 1.下载最新的Hbase,这里我下载的是hbase ...
- BZOJ1407 [Noi2002]Savage 【扩展欧几里得】
题目链接 BZOJ1407 题解 枚举\(m\)用扩欧判即可 #include<algorithm> #include<iostream> #include<cstrin ...
- 【BZOJ 3144】 [Hnoi2013]切糕 真·最小割
一开始一脸懵逼后来发现,他不就是割吗,我们只要满足条件就割就行了,于是我们把他连了P*Q*R条边,然而我们要怎样限制D呢?我们只要满足对于任意相邻的两条路,只要其有个口大于D就不行就好了因此我们只要把 ...
- 使用setTimeout延时10ms执行onunloadcancel
在做Web开发时,我们经常用到页面关闭事件onbeforeunload,可以给用户一个选择放弃关闭的机会,就比如这个博客编辑器.如果用户选择了离开,那么onunload事件自然会触发:但若用户选择了取 ...
- Idea 怎么远程debug
注意的问题:远程debug别人的服务器只能开一个debug,所以当你的同事比你先远程debug同一台服务器时,你应该报Error running 某某ip地址 .unable to open debu ...
- java程序在centos7里面开机自启动
1.我们先来个简单的start,status,stop程序: [root@localhost ~]# cat /home/tomcat/jarservice.sh #!/bin/bashCU_PID= ...
- [06] 盒模型 + auto 居中 + 垂直合并
1.盒模型 盒子模型有两种,分别是 ie 盒子模型和标准 w3c 盒子模型. 标准(W3C)模型中:CSS中的宽(width) = 内容 (content)的宽 CSS中的宽(width) = 内容( ...
- Servlet的doGet与doPost方法的区别与使用
Servlet的doGet与doPost方法的区别与使用 2016年07月07日 13:05:13 阅读数:10222 一,区别 在使用表单提交数据到服务器的时候有两张方式可共选择,一个是post一个 ...
- bzoj1577 [Usaco2009 Feb]庙会捷运Fair Shuttle
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1577 [题解] 我们把每坨奶牛按s排个序. 对于每坨奶牛,如果车上有空位置就塞. 否则,看下 ...
- 斜率优化DP讲解
对于斜率优化的DP转移方程,一般以w[i]=max(w[j]+(sum[i]-sum[j])*v)的1D1D形式为主,直观看来就是前j个为若干个阶段,第j+1到第i个为一个阶段,每个阶段有自己的代价或 ...