[CodeVS2370] 小机房的树 (LCA, 树链剖分, LCT)
Description
Input
第一行一个n,接下来n-1行每一行有三个整数u,v, c 。表示节点 u 爬到节点 v 需要花费 c 的精力。
第n+1行有一个整数m表示有m次询问。接下来m行每一行有两个整数 u ,v 表示两只虫子所在的节点
Output
一共有m行,每一行一个整数,表示对于该次询问所得出的最短距离。
Sample Input
Sample Output
HINT
1<=n<=50000, 1<=m<=75000, 0<=c<=1000
Source
Solution
倍增求LCA, $O((n + m)logn)$
#include <bits/stdc++.h>
using namespace std;
struct edge
{
int v, w, nxt;
}e[];
int fst[], q[], front, back;
int fa[][], dis[], dep[]; void addedge(int i, int u, int v, int w)
{
e[i] = (edge){v, w, fst[u]}, fst[u] = i;
} int LCA(int u, int v)
{
if(dep[u] > dep[v]) swap(u, v);
for(int i = ; ~i; i--)
if(dep[fa[i][v]] >= dep[u])
v = fa[i][v];
if(u == v) return u;
for(int i = ; ~i; i--)
if(fa[i][u] != fa[i][v])
u = fa[i][u], v = fa[i][v];
return fa[][u];
} int main()
{
int n, m, u, v, w;
cin >> n;
for(int i = ; i < n; i++)
{
cin >> u >> v >> w;
addedge(i << , ++u, ++v, w);
addedge(i << | , v, u, w);
}
q[++back] = , dep[] = fa[][] = ;
while(front != back)
{
u = q[++front];
for(int i = fst[u]; i; i = e[i].nxt)
if(e[i].v != fa[][u])
{
q[++back] = e[i].v;
dep[e[i].v] = dep[u] + ;
fa[][e[i].v] = u;
dis[e[i].v] = dis[u] + e[i].w;
}
}
for(int i = ; i <= ; i++)
for(int j = ; j <= n; j++)
fa[i][j] = fa[i - ][fa[i - ][j]];
cin >> m;
while(m--)
{
cin >> u >> v, u++, v++;
cout << dis[u] + dis[v] - * dis[LCA(u, v)] << endl;
}
return ;
}
Tarjan求LCA, $O(n + m)$(写法较鬼畜)
#include <bits/stdc++.h>
using namespace std;
struct edge
{
int v, w, nxt;
}e[];
struct query
{
int u, v, nxt;
}q[];
int efst[], qfst[], fa[], lca[], dis[];
bool vis[]; void addedge(int i, int u, int v, int w)
{
e[i] = (edge){v, w, efst[u]}, efst[u] = i;
} void addquery(int i, int u, int v)
{
q[i] = (query){u, v, qfst[u]}, qfst[u] = i;
} int get_dis(int i)
{
return dis[q[i << ].u] + dis[q[i << ].v] - * dis[lca[i]];
} int getfa(int x)
{
return fa[x] = x == fa[x] ? x : getfa(fa[x]);
} void Tarjan(int u)
{
fa[u] = u, vis[u] = true;
for(int i = efst[u]; i; i = e[i].nxt)
if(!vis[e[i].v])
{
dis[e[i].v] = dis[u] + e[i].w;
Tarjan(e[i].v);
fa[e[i].v] = u;
}
for(int i = qfst[u]; i; i = q[i].nxt)
{
int v = q[i].u == u ? q[i].v : q[i].u;
if(vis[v]) lca[i >> ] = getfa(fa[v]);
}
} int main()
{
int n, m, u, v, w;
cin >> n;
for(int i = ; i < n; i++)
{
cin >> u >> v >> w;
addedge(i << , ++u, ++v, w);
addedge(i << | , v, u, w);
}
cin >> m;
for(int i = ; i <= m; i++)
{
cin >> u >> v;
addquery(i << , ++u, ++v);
addquery(i << | , v, u);
}
Tarjan();
for(int i = ; i <= m; i++)
cout << get_dis(i) << endl;
return ;
}
树链剖分求LCA, $O(mlogn)$,我习惯把树剖维护的7个信息写到结构体里。
#include <bits/stdc++.h>
using namespace std;
struct edge
{
int v, w, nxt;
}e[];
struct point
{
int fa, siz, son, dep, dis, dfn, top;
}p[];
int ptot, fst[]; void addedge(int i, int u, int v, int w)
{
e[i] = (edge){v, w, fst[u]}, fst[u] = i;
} void DFS1(int u)
{
p[u].siz = ;
for(int i = fst[u]; i; i = e[i].nxt)
if(e[i].v != p[u].fa)
{
p[e[i].v].fa = u;
p[e[i].v].dep = p[u].dep + ;
p[e[i].v].dis = p[u].dis + e[i].w;
DFS1(e[i].v);
p[u].siz += p[e[i].v].siz;
if(p[e[i].v].siz > p[p[u].son].siz)
p[u].son = e[i].v;
}
} void DFS2(int u, int top)
{
p[u].dfn = ++ptot, p[u].top = top;
if(p[u].son) DFS2(p[u].son, top);
for(int i = fst[u]; i; i = e[i].nxt)
if(e[i].v != p[u].fa && e[i].v != p[u].son)
DFS2(e[i].v, e[i].v);
} int LCA(int u, int v)
{
while(p[u].top != p[v].top)
{
if(p[p[u].top].dep > p[p[v].top].dep) swap(u, v);
v = p[p[v].top].fa;
}
if(p[u].dep > p[v].dep) swap(u, v);
return u;
} int main()
{
int n, m, u, v, w;
cin >> n;
for(int i = ; i < n; i++)
{
cin >> u >> v >> w;
addedge(i << , ++u, ++v, w);
addedge(i << | , v, u, w);
}
p[].dep = , DFS1(), DFS2(, );
cin >> m;
while(m--)
{
cin >> u >> v, u++, v++;
cout << p[u].dis + p[v].dis - * p[LCA(u, v)].dis << endl;
}
return ;
}
LCT, $O(mlog^{2}n)$
#include <bits/stdc++.h>
using namespace std;
struct LCT
{
int fa, c[], rev, key, sum;
int& operator [] (int i)
{
return c[i];
}
}a[];
int sta[], top; void push_up(int k)
{
a[k].sum = a[a[k][]].sum + a[a[k][]].sum + a[k].key;
} void push_down(int k)
{
if(a[k].rev)
{
a[a[k][]].rev ^= , a[a[k][]].rev ^= ;
swap(a[k][], a[k][]), a[k].rev = ;
}
} bool isroot(int x)
{
return a[a[x].fa][] != x && a[a[x].fa][] != x;
} void rotate(int x)
{
int y = a[x].fa, z = a[y].fa;
int dy = a[y][] == x, dz = a[z][] == y;
if(!isroot(y)) a[z][dz] = x;
a[y][dy] = a[x][dy ^ ], a[a[x][dy ^ ]].fa = y;
a[x][dy ^ ] = y, a[y].fa = x, a[x].fa = z;
push_up(y);
} void splay(int x)
{
sta[top = ] = x;
for(int i = x; !isroot(i); i = a[i].fa)
sta[++top] = a[i].fa;
while(top)
push_down(sta[top--]);
while(!isroot(x))
{
int y = a[x].fa, z = a[y].fa;
if(!isroot(y))
if(a[y][] == x ^ a[z][] == y) rotate(x);
else rotate(y);
rotate(x);
}
push_up(x);
} void access(int x)
{
for(int i = ; x; x = a[x].fa)
splay(x), a[x][] = i, i = x;
} void make_root(int x)
{
access(x), splay(x), a[x].rev ^= ;
} void link(int x, int y)
{
make_root(x), a[x].fa = y;
} void cut(int x, int y)
{
make_root(x), access(y), splay(y), a[y][] = a[x].fa = ;
} int find_root(int x)
{
access(x), splay(x);
while(a[x][])
x = a[x][];
return x;
} int main()
{
int n, m, u, v, w;
cin >> n;
for(int i = ; i < n; i++)
{
cin >> u >> v >> w;
a[i + n].sum = a[i + n].key = w;
link(++u, i + n), link(i + n, ++v);
}
cin >> m;
while(m--)
{
cin >> u >> v;
make_root(++u), access(++v), splay(v);
printf("%d\n", a[v].sum);
}
return ;
}
[CodeVS2370] 小机房的树 (LCA, 树链剖分, LCT)的更多相关文章
- Count on a tree SPOJ 10628 主席树+LCA(树链剖分实现)(两种存图方式)
Count on a tree SPOJ 10628 主席树+LCA(树链剖分实现)(两种存图方式) 题外话,这是我第40篇随笔,纪念一下.<( ̄︶ ̄)↗[GO!] 题意 是说有棵树,每个节点上 ...
- codevs2370 小机房的树 x
2370 小机房的树 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 题目描述 Description 小机房有棵焕狗种的树,树上有N个节点,节点标号 ...
- codevs2370 小机房的树
题目描述 Description 小机房有棵焕狗种的树,树上有N个节点,节点标号为0到N-1,有两只虫子名叫飘狗和大吉狗,分居在两个不同的节点上.有一天,他们想爬到一个节点上去搞基,但是作为两只虫子, ...
- Bzoj 2243: [SDOI2011]染色 树链剖分,LCT,动态树
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 5020 Solved: 1872[Submit][Status ...
- Bzoj 1036: [ZJOI2008]树的统计Count 树链剖分,LCT
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 11102 Solved: 4490[Submit ...
- [FJOI2014]最短路径树问题 长链剖分
[FJOI2014]最短路径树问题 LG传送门 B站传送门 长链剖分练手好题. 如果你还不会长链剖分的基本操作,可以看看我的总结. 这题本来出的很没水平,就是dijkstra(反正我是不用SPFA)的 ...
- BZOJ2243: [SDOI2011]染色(树链剖分/LCT)
Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段), 如 ...
- 【bzoj4811】[Ynoi2017]由乃的OJ 树链剖分/LCT+贪心
Description 给你一个有n个点的树,每个点的包括一个位运算opt和一个权值x,位运算有&,l,^三种,分别用1,2,3表示. 每次询问包含三个数x,y,z,初始选定一个数v.然后v依 ...
- [codevs2370]小机房的树<LCA>
题目链接:http://codevs.cn/problem/2370/ 这题我还是做了比较久了,因为有人告诉我这是用tarjan离线做 好吧算我是蒟蒻,真心不懂tarjan怎么做,最后还是用倍增做的 ...
随机推荐
- Function与Object的关系
这里先简单介绍一下我研究这个问题的初衷.起初我只是想研究一下原型链的基本思想.构造函数拥有prototype属性,指向它的prototype,而该构造函数的实例化对象则拥有一个[[prototype] ...
- Linux中的 awk查找日志中的相关记录
假设要在 api.log.201707201830 文件中,(此文件的多个字段数据以不可见字符^A(键盘上按下Ctrl+V+A)分隔),要输出第70个字段: awk -F '^A' '{print $ ...
- angularjs 控制器、作用域、广播详解
一.控制器 首先列出几种我们平常使用控制器时的几种误区: 我们知道angualrJs中一个控制器时可以对应不同的视图模板的,但这种实现方式存在的问题是: 如果视图1和视图2根本没有任何逻辑关系,这样& ...
- 微信小程序Md5加密(utf-8汉字无影响)
微信小程序不让使用第三方jqMD5 只好改原生js咯 废话不多说直接贴代码 其实就是将原生function调用改为 module.exports = md5; 文中 红色标注 使用方法 将md5.js ...
- HashMap、Hashtable、 LinkedHashMap、TreeMap四者之分。
java为数据结构中的映射定义了一个接口java.util.Map,此接口主要有四个常用的实现类,分别是HasMap.Hashtable.LinkedHasmap和TreeMap. (1)HashMa ...
- CentOS7关闭/开启防火墙出现 Unit iptables.service failed to load
在vm中安装好tomcat,而且在liunx中使用nc命令可以返回成功,但是更换到window中访问不到tomcat的情况,是由于linux防火墙的问题造成的,传统的解决方式有2中 第一种解决方案: ...
- Ubuntu下Maven配置与Maven项目创建教程
一. Ubuntu下Maven配置 windows下Maven配置参考http://www.cnblogs.com/LexMoon/p/JavaMaven.html ubuntu下Maven地址htt ...
- AssetBundle实现服务器下载并从本地读取
废话不多说 直接上代码. 从服务器下载的, 很简单 private IEnumerator Start() { byte[] ab = null; int len = 0; WWW www =nul ...
- 长整形的使用及cin加速
_int64 和 long long 那么对ACMer来说,最为关心的就是在各个OJ上交题应分别使用哪种方式了.其实方式只有有限的几种: 如果服务器是linux系统,那么定义用long long,IO ...
- HDU - 1847 巴什博弈
思路: 0 1 2 3 4 5 6 7 8 9 10 11 12 P N N P N N P N N P N N P 不难发现:当n为三的倍数时,KIKI ...