「刷题笔记」LCA问题相关
板子
ll lg[40];
ll dep[N],fa[N][40];
ll dis[N];
void dfs(ll u,ll f)
{
dep[u]=dep[f]+1;
fa[u][0]=f;
for(int i=1;i<=lg[dep[u]];i++)
{
fa[u][i]=fa[fa[u][i-1]][i-1];
}
for(int i=head[u];i;i=next[i])
{
ll v=e[i].v;
if(v==f)continue;
dis[v]=dis[u]+e[i].w;
dfs(v,u);
}
}
ll lca(ll a,ll b)
{
if(dep[a]<dep[b])swap(a,b);
while(dep[a]>dep[b])
{
a=fa[a][lg[dep[a]-dep[b]]];
}
if(a==b)return a;
for(int i=lg[dep[a]];i>=0;i--)
{
if(fa[a][i]!=fa[b][i])
{
a=fa[a][i];
b=fa[b][i];
}
}
return fa[a][0];
}
void lgp()
{
for(int i=2;i<=n;i++)
{
lg[i]=lg[i-1]+((2<<lg[i-1])==i);
}
}
牧场旅行
记一个比较容易的结论:
树上路径长:
\]
这道题就是用这个结论套\(lca\)板子
然后注意写不要在\(if\)语句的同行加分号……(就是直接判了个寂寞)
Distance Queries 距离咨询
怕不是和牧场旅行完全重题……
记下是因为要注意预处理\(lg\)数组的时候是从\(1\)开始的
然后输入的方向根本没用……
货车运输&&星际导航
这两题就只是最大最小相反好吧……
之前学树剖的时候做过货车这道题,树剖方法见这篇博客
这里记一下倍增方法
首先容易想到这条符合题意的路径肯定是在无向图的最大/最小生成树上的,于是先用\(kruskal\)把这棵树抠出来,然后树上倍增求即可
相当于一个树上的\(RMQ\),所以用倍增解决,跟求\(lca\)时差不了太多,就是多维护了一个区间最值数组,然后跳的时候顺便记得用它更新答案
再就是\(kruskal\)之前先把边存在别的地方,要不会出玄学错误……
代码(以货车运输为例)
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define ZZ_zuozhe int main()
#define N 50005
#define E 500005
ll n,m,a,b,c,q;
struct edge
{
ll u,v,w;
}e[E],t[E];
ll tot=0,head[E],next[E];
void add(ll a,ll b,ll c)
{
++tot;
e[tot].u=a;
e[tot].v=b;
e[tot].w=c;
next[tot]=head[a];
head[a]=tot;
}
bool cmp(edge a,edge b)
{
return a.w>b.w;
}
ll lg[E];
void lgp()
{
for(int i=2;i<=m;i++)lg[i]=lg[i>>1]+1;
}
ll dep[N],fa[N][30],mx[N][30];
void dfs(ll u,ll f)
{
dep[u]=dep[f]+1;
fa[u][0]=f;
for(int i=1;i<=lg[dep[u]];i++)
{
fa[u][i]=fa[fa[u][i-1]][i-1];
}
for(int i=head[u];i;i=next[i])
{
ll v=e[i].v;
if(v==f)continue;
mx[v][0]=e[i].w;
dfs(v,u);
}
}
void mxp()
{
for(int j=1;j<=lg[n];j++)
{
for(int i=1;i<=n;i++)
{
mx[i][j]=min(mx[i][j-1],mx[fa[i][j-1]][j-1]);
}
}
}
ll f[N];
ll fd(ll a)
{
if(f[a]==a)return a;
else return f[a]=fd(f[a]);
}
void uni(ll a,ll b)
{
ll x=fd(a),y=fd(b);
f[y]=x;
}
void kruskal()
{
sort(t+1,t+m+1,cmp);
memset(head,0,sizeof head);
tot=0;
for(int i=1;i<=n;i++)f[i]=i;
for(int i=1;i<=m;i++)
{
ll a=t[i].u,b=t[i].v,c=t[i].w;
if(fd(a)!=fd(b))
{
uni(a,b);
add(a,b,c);
add(b,a,c);
}
}
}
ll lca(ll a,ll b)
{
ll res=1000000000000000000;
if(dep[a]<dep[b])swap(a,b);
while(dep[a]>dep[b])
{
res=min(res,mx[a][lg[dep[a]-dep[b]]]);
a=fa[a][lg[dep[a]-dep[b]]];
}
if(a==b)return res;
for(int i=lg[dep[a]];i>=0;i--)
{
if(fa[a][i]!=fa[b][i])
{
res=min(res,mx[a][i]);
res=min(res,mx[b][i]);
a=fa[a][i];
b=fa[b][i];
}
}
res=min(res,mx[a][0]);
res=min(res,mx[b][0]);
return res;
}
ZZ_zuozhe
{
//freopen("owo.in","r",stdin);
//freopen("awa.out","w",stdout);
scanf("%lld%lld",&n,&m);
lgp();
for(int i=1;i<=m;i++)
{
scanf("%lld%lld%lld",&t[i].u,&t[i].v,&t[i].w);
}
kruskal();
dep[0]=0;
for(int i=1;i<=n;i++)if(!dep[i])dfs(i,0);
mxp();
scanf("%lld",&q);
for(int i=1;i<=q;i++)
{
scanf("%lld%lld",&a,&b);
if(fd(a)!=fd(b))puts("-1");
else printf("%lld\n",lca(a,b));
}
return 0;
}
bzoj3306 树
就是遥远的国度嘛\(qaq\)
这篇博客里有思路和树剖的版本,这里给出倍增方法的
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define ZZ_zuozhe int main()
#define N 200005
ll n,q,a,b,root,rt;
char ch[3];
struct edge
{
ll u,v;
}e[N];
ll tot=0,head[N],next[N];
void add(ll a,ll b)
{
++tot;
e[tot].u=a;
e[tot].v=b;
next[tot]=head[a];
head[a]=tot;
}
ll lg[N];
void lgp()
{
for(int i=2;i<=n;i++)lg[i]=lg[i>>1]+1;
}
ll dep[N],fa[N][30];
ll l[N],r[N],cnt=0;
ll num[N],w[N];
void dfs(ll u,ll f)
{
l[u]=++cnt;
num[l[u]]=w[u];
fa[u][0]=f;
dep[u]=dep[f]+1;
for(int i=1;i<=lg[dep[u]];i++)
{
fa[u][i]=fa[fa[u][i-1]][i-1];
}
for(int i=head[u];i;i=next[i])
{
ll v=e[i].v;
if(v==f)continue;
dfs(v,u);
}
r[u]=cnt;
}
ll lca(ll a,ll b)
{
if(dep[a]<dep[b])swap(a,b);
while(dep[a]>dep[b])
{
a=fa[a][lg[dep[a]-dep[b]]];
}
if(a==b)return a;
for(int i=lg[dep[a]];i>=0;i--)
{
if(fa[a][i]!=fa[b][i])
{
a=fa[a][i];
b=fa[b][i];
}
}
return fa[a][0];
}
#define lson rt<<1,l,m
#define rson rt<<1|1,m+1,r
ll tree[N<<2];
void upd(ll rt)
{
tree[rt]=min(tree[rt<<1],tree[rt<<1|1]);
}
void build(ll rt,ll l,ll r)
{
if(l==r)
{
tree[rt]=num[l];//cout<<l<<' '<<tree[rt]<<endl;
return;
}
ll m=(l+r)>>1;
build(lson);
build(rson);
upd(rt);
}
void change(ll rt,ll l,ll r,ll n,ll val)
{
if(l==r)
{
tree[rt]=val;
return;
}
ll m=(l+r)>>1;
if(m>=n)change(lson,n,val);
if(m<n)change(rson,n,val);
upd(rt);
}
ll query(ll rt,ll l,ll r,ll nl,ll nr)
{
if(nl<=l&&r<=nr)
{
//cout<<' '<<tree[rt]<<endl;
return tree[rt];
}
ll m=(l+r)>>1;
ll ans=1000000000000000000;
if(m>=nl)ans=min(ans,query(lson,nl,nr));
if(m<nr)ans=min(ans,query(rson,nl,nr));
return ans;
}
ZZ_zuozhe
{
//freopen("owo.in","r",stdin);
scanf("%lld%lld",&n,&q);
lgp();
for(int i=1;i<=n;i++)
{
scanf("%lld%lld",&a,&w[i]);
if(a)add(a,i);
if(a==0)root=i;
}
dfs(root,0);
rt=root;
build(1,1,n);
for(int i=1;i<=q;i++)
{
scanf("%s",ch);
if(ch[0]=='V')
{
scanf("%lld%lld",&a,&b);
//cout<<'\t'<<l[a]<<' '<<b<<endl;
change(1,1,n,l[a],b);
}
else if(ch[0]=='E')
{
scanf("%lld",&rt);
}
else if(ch[0]=='Q')
{
scanf("%lld",&a);
//cout<<' '<<a<<' '<<rt<<endl;
if(a==rt)printf("%lld\n",tree[1]);
else if(l[a]>l[rt]||r[a]<l[rt])printf("%lld\n",query(1,1,n,l[a],r[a]));
else
{
ll now=rt;
for(int i=16;i>=0;i--)
{
if(dep[fa[now][i]]>dep[a])now=fa[now][i];
}
printf("%lld\n",min(query(1,1,n,1,l[now]-1),query(1,1,n,r[now]+1,n)));
}
}
}
}
「刷题笔记」LCA问题相关的更多相关文章
- 「刷题笔记」AC自动机
自动AC机 Keywords Research 板子题,同luoguP3808,不过是多测. 然后多测不清空,\(MLE\)两行泪. 板子放一下 #include<bits/stdc++.h&g ...
- 「刷题笔记」DP优化-状压-EX
棋盘 需要注意的几点: 题面编号都是从0开始的,所以第1行实际指的是中间那行 对\(2^{32}\)取模,其实就是\(unsigned\ int\),直接自然溢出啥事没有 棋子攻击范围不会旋转 首先, ...
- 「刷题笔记」Tarjan
贴一个讲得非常详细的\(tarjan\)入门教程 信息传递 讲个笑话:我之前用并查集求最小环过的这题,然后看见题目上有个\(tarjan\)标签 留下了深刻的印象:\(tarjan\)就是并查集求最小 ...
- 「刷题笔记」哈希,kmp,trie
Bovine Genomics 暴力 str hash+dp 设\(dp[i][j]\)为前\(i\)组匹配到第\(j\)位的方案数,则转移方程 \[dp[i][j+l]+=dp[i-1][j] \] ...
- 《Data Structures and Algorithm Analysis in C》学习与刷题笔记
<Data Structures and Algorithm Analysis in C>学习与刷题笔记 为什么要学习DSAAC? 某个月黑风高的夜晚,下班的我走在黯淡无光.冷清无人的冲之 ...
- Python 刷题笔记
Python 刷题笔记 本文记录了我在使用python刷题的时候遇到的知识点. 目录 Python 刷题笔记 选择.填空题 基本输入输出 sys.stdin 与input 运行脚本时传入参数 Pyth ...
- ☕【JVM技术指南】「JVM总结笔记」Java虚拟机垃圾回收认知和调优的"思南(司南)"【下部】
承接上文 (完结撒花1-52系列)[JVM技术指南]「JVM总结笔记」Java虚拟机垃圾回收认知和调优的"思南(司南)"[上部] 并行收集器 并行收集器(也称为吞吐量收集器)是类似 ...
- PTA刷题笔记
PTA刷题记录 仓库地址: https://github.com/Haorical/Code/tree/master/PTA/GPLT 两周之内刷完GPLT L2和L3的题,持续更新,包括AK代码,坑 ...
- 看完互联网大佬的「LeetCode 刷题手册」, 手撕了 400 道 Leetcode 算法题
大家好,我是 程序员小熊 ,来自 大厂 的程序猿.相信绝大部分程序猿都有一个进大厂的梦想,但相较于以前,目前大厂的面试,只要是研发相关岗位,算法题基本少不了,所以现在很多人都会去刷 Leetcode ...
随机推荐
- python爬虫使用xpath解析页面和提取数据
XPath解析页面和提取数据 一.简介 关注公众号"轻松学编程"了解更多. XPath即为XML路径语言,它是一种用来确定XML(标准通用标记语言的子集)文档中某部分位置的语言.X ...
- 热部署只知道devtools吗?JRebel不香吗?
持续原创输出,点击上方蓝字关注我 目录 前言 JRebel收费怎么破? 什么是本地热部署? 什么是远程热部署? JRebel和devtools的区别 如何安装JRebel? 如何本地热部署? 如何远程 ...
- springcloud feign使用
1.Spring cloud fein的继承特性 通过对接口的继承,能够实现对fein客户端和feign服务器代码量的减少. 2.Ribbon配置 {服务名}.ribbon.ConnectTimeOu ...
- c#集合随机数
List<int> list = new List<int>(10); Random r=new Random(); int num = 0; for (int i = 0; ...
- 剑指Offer-Python(16-20)
16.合并另个排序链表 # -*- coding:utf-8 -*- class ListNode: def __init__(self, x): self.val = x self.next = N ...
- Python爬虫-换行的匹配
之前在学习爬虫的时候遇到了匹配内容时发现存在换行,这时没法匹配了,后来在网上找到了一种方法,当时懒得记录,今天突然有遇到了这种情况,想想还是在这里记录一下吧. 当时爬取的时csdn首页博客,如下图 看 ...
- MySql索引使用策略
MySql索引 索引优点 1.可以通过建立唯一索引或者主键索引,保证数据的唯一性.2.提高检索的数据性能3.在表连接的连接条件 可以加速表与表直接的相连 4.建立索引,在查询中使用索引 可以提高性能 ...
- 在java9+版本中,接口的内容和注意
1.成员变量其实就是常量,格式: [public] [static] [final] 数据类型 常量名称 = 数据值: 注意: 常量必须进行赋值,而且一旦赋值不能改变. 常量名称完全大写,用下划线进行 ...
- Java 中数组转换为 List
目录 1 - int 型数组转换为 List 2 - List 转换为 int 型数组 3 - String 型数组转换为 List 4 - List 转换为 String 型数组 版权声明 开发中经 ...
- java小工具,使用Swing展示左树右表结构
代码直接上: 入口类 import java.io.File; import java.util.ArrayList; import java.util.List; import org.json.J ...