「刷题笔记」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 ...
随机推荐
- 妙用 Intellij IDEA 创建临时文件,Git 跟踪不到的那种
| 好看请赞,养成习惯 你有一个思想,我有一个思想,我们交换后,一个人就有两个思想 If you can NOT explain it simply, you do NOT understand it ...
- STM32CubeIDE下载安装-GPIO基本配置操作-Debug调试(基于CMSIS DAP Debug)
1.在ST官网下载STM32CubeIDE而不是STM32CubeMX,并且STM32CubeIDE是免费的.(STM32CubeIDE不支持中文路径,不然编译会出错) 2.如果你用的是keil开发环 ...
- VSCode--HTML代码片段(基础版,react、vue、jquery)
起因是最近在学习前端,看的网上的demo也是在react.vue.jquery之间穿插,为了方便一键生成html模板(懒)写demo,有了以下折腾. 本人使用的前端编辑工具是vscode(方便.懒), ...
- Docker 实战(2)- 配置 Jenkins 容器上的持续集成环境
如果你还想从头学起 Docker,可以看看这个系列的文章哦! https://www.cnblogs.com/poloyy/category/1870863.html 搭建 Jenkins 容器 就是 ...
- 基于gin的golang web开发:mysql增删改查
Go语言访问mysql数据库需要用到标准库database/sql和mysql的驱动.标准库的Api使用比较繁琐这里再引入另一个库github.com/jmoiron/sqlx. go get git ...
- 无字母数字getshell
无字母数字webshell 预备知识 一些不包含数字和字母的webshell https://www.leavesongs.com/PENETRATION/webshell-without-alpha ...
- tcpack--3快速确认模式
接收到数据报后,会调用tcp_event_data_recv(),不管是在慢速路径的tcp_data_queue中调用还是 在快速路径中处理接收数据后直接调用,注意(如果len <= tcp_h ...
- netty简介2
作者:知乎用户 链接:https://www.zhihu.com/question/24322387/answer/282001188 来源:知乎 著作权归作者所有.商业转载请联系作者获得授权,非商业 ...
- CSS z-index应用靠近用户的框
1.z-index (1)z轴.数值越大,越靠近你 (2)只能作用于定位过的标签元素 应用示例 <!DOCTYPE html> <html lang="zh-CN" ...
- Dubbo 服务引入-Version2.7.5
1.服务引用原理 Dubbo 服务引用的时机有两个,第一个是在 Spring 容器调用 ReferenceBean 的 afterPropertiesSet 方法时引用服务,第二个是在 Referen ...