开拓计划21/2025集训作业表3 - 倍增ST表LCA次小生成树

news/2025/1/5 18:12:57/文章来源:https://www.cnblogs.com/hsr-ray-blog/p/18615748

开拓计划21/2025集训作业表3 - 倍增&ST表&LCA&次小生成树

倍增&ST表

概念

  • Q:倍增是什么?
  • A:倍增,顾名思义是成倍增长的意思,它利用了二进制的性质和预处理(俗称打表)的思想,在 \(O(\log n)\) 内完成一些操作。
  • Q:ST表是什么?
  • A:ST表主要用于解决RMQ(区间最值问题),它用了打表的思想,但是没有将表打完整。

ST表的原理

在实现 RMQ 问题时,我们可以通过打表来提升效率。提前计算出 \([l,r]\) 的答案。但是这样打表就需要 \(O(n^2)\) 实在是太浪费时间了。于是我们发现,表没必要打得这么详细,我们设 \(f_{i,j}\) 表示区间 \([i,i+2^j-1]\) 的最大值。

预处理:

  • \(f_{i,0}=a_i\)
  • \(f_{i,j}=\max(f_{i,j-1},f_{i+2^{j-1},j-1})\)
  • 时间复杂度 \(O(n \log n)\)

查询:

  • 如果要查询区间 \([l,r]\),先找 \(2^j \le r-l+1\)\(j\) 的最大值。
    \(\therefore j=\lfloor \log_2(r-l+1) \rfloor\)
  • \(ans=\max(f_{l,j},f_{r-2^j+1,j})\)
  • 时间复杂度 \(O(n)\)

ST表的代码

#include<bits/stdc++.h>
using namespace std;
const int N=25005;
int f[N][35];
int main(){ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);int n,q;cin>>n>>q;for(int i=1;i<=n;i++) cin>>f[i][0];int mx=log2(n);//预处理for(int j=1;j<=mx;j++){int i,k=(1<<j-1);for(i=1;i<=n-k;i++) f[i][j]=min(f[i][j-1],f[i+k][j-1]);for(;i<=n;i++) f[i][j]=f[i][j-1];}//查询for(int i=1;i<=q;i++){int l,r;cin>>l>>r;int j=log2(r-l+1);cout<<min(f[l][j],f[r-(1<<j)+1][j])<<"\n";}return 0;
}

LCA

概念

  • Q:LCA 是什么?
  • A:LCA是指树上最近公共祖先,如下图所示,\(7\)\(5\) 的 LCA 就是\(2\)

求法

倍增法

还是要求 \(7\)\(5\) 的LCA。
\(f_{i,j}\) 表示第 \(i\) 个节点,跳 \(2^j\) 步的时候跳到的位置,\(x\)\(y\) 分别为 \(5\)\(7\) 的指针。
分为两个阶段:

  • 第一阶段:将 \(7\)\(5\) 的指针调整到同一高度。
    • 通过已经预处理的 \(f\) 数组开始尝试跳,如果高度大了就是条过头了,回去重新跳,直到 \(x\) 的新高度小于 \(y\),就往上跳,跳完了再继续跳,直到高度一样。
  • 第二阶段
    • 两个指针同时开始向上跳,跳过头了就回来,直到跳到同一个点。
倍增求LCA的代码
void dfs(int x,int fa){dep[x]=dep[fa]+1;f[x][0]=fa;for(int j=1;;j++){f[x][j]=f[f[x][j-1]][j-1];if(f[x][j]==0){mx=max(mx,j-1);break;}}for(auto i:vt[x]){if(i!=fa) dfs(i,x);}
}
int Lca(int x,int y){if(dep[x]<dep[y]) swap(x,y);for(int j=mx;j>=0;j--){if(dep[f[x][j]]>=dep[y]) x=f[x][j];}if(x==y) return x;for(int j=mx;j>=0;j--){if(f[x][j]!=f[y][j]) x=f[x][j],y=f[y][j];}return f[x][0];
}

次小生成树

非严格次小生成树

思路:

  • 先用 kurskal 求最小生成树。
  • 枚举最小生成树以外的边,将每一条边分别加入再减掉原来的最大边。
  • 求所有结果的最小值。

代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=100005;
int dep[N],f[N][35],fa[N],used[N<<1],dis[N][35];
int n,m,Ans=0;
struct node{int s,e,w;}edge[N<<1];
struct nodf{int v,e;};
bool cmp(node a,node b){return a.w<b.w;}
vector<nodf> vt[N];
void dfs(int x,int fa){for(int j=1;(1<<j)<=dep[x];j++){f[x][j]=f[f[x][j-1]][j-1];dis[x][j]=max(dis[f[x][j-1]][j-1],dis[x][j-1]);}for(auto i:vt[x]){if(i.v!=fa){dep[i.v]=dep[x]+1;f[i.v][0]=x;dis[i.v][0]=i.e;dfs(i.v,x);}}
}
int Lca(int x,int y){int mx=0;if(dep[x]<dep[y]) swap(x,y);for(int j=30;j>=0;j--){if(dep[x]-(1<<j)>=dep[y]){mx=max(dis[x][j],mx);x=f[x][j];}}if(x==y) return mx;for(int j=30;j>=0;j--){if(f[x][j]!=f[y][j]){mx=max(dis[x][j],mx);mx=max(dis[y][j],mx);x=f[x][j],y=f[y][j];}}return max(mx,max(dis[x][0],dis[y][0]));
}
int getf(int x){if(x==fa[x]) return x;return fa[x]=getf(fa[x]); 
}
bool kurskal(){int cnt=0;for(int i=1;i<=m;i++){if(cnt==n-1) return 0;if(getf(edge[i].s)!=getf(edge[i].e)){cnt++;fa[getf(edge[i].s)]=getf(edge[i].e);used[i]=1;Ans+=edge[i].w;vt[edge[i].s].push_back({edge[i].e,edge[i].w});vt[edge[i].e].push_back({edge[i].s,edge[i].w});}}return 1;
}
signed main(){ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);cin>>n>>m;for(int i=1;i<=n;i++) fa[i]=i;for(int i=1;i<=m;i++) cin>>edge[i].s>>edge[i].e>>edge[i].w;sort(edge+1,edge+1+m,cmp);if(kurskal()){cout<<"Keng Die!";return 0;}dep[1]=1;dfs(1,0);int ans=0x7fffffff;for(int i=1;i<=m;i++){if(used[i]==0){ans=min(ans,Ans+edge[i].w-Lca(edge[i].s,edge[i].e));}}cout<<ans;return 0;
}

严格次小生成树

思路

同非严格只不过要同时维护次大值,因为相等的时候就需要换成次大值。

代码

oi wiki

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/862437.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

系统管理体系之进程管理

系统管理体系之进程管理 1. 进程名字 含义程序 安装包,程序代码,app,存放在磁盘上面.进程⭐️ 运行起来的程序,命令,服务(远程连接服务,网络服务)都可以称作进程。 运行在内存中。守护进程 守护进程, 一直运行的进程. 也可以叫做服务.2. 进程分类(异常进程) 2.1 僵尸进程⭐️⭐…

系统管理之服务管理---管理命令

1. 系统管理之服务管理---管理命令systemctl 管理服务开机自启动管理正在运行的服务.旧版本的系统:Centos 5.x 6.x 需要使用service 命令检查 sshd 远程连接服务状态systemctl status sshd systemctl status 单个或多个服务名如何设置开启开机自启动 systemctl enable sshd 当…

夜之向日葵

2024 ECF 游记 Day 0 我早就预感到 ecf 要寄,但没想到寄得这么彻底。 比赛之前,我去做了去年 ecf 的题目,发现里面的可做题全部都是贪心,性质和结论题。众所周知,chino 最不擅长的题目类型就是这些。 同时,因为周一周二要考大物和数分,比赛前的一周几乎没有训练。 于是就…

网络流初步

网络流初步(脑部整理) 呜呜呜,家人们也是学上网络流了。 咸鱼起手,你反应得过来吗? 英语不太好(老英不会看窝博客吧) What is 网络流?概述 网络\((network)\)是指一个特殊的有向图 \(G=(V,E)\),其与一般有向图的不同之处在于有容量和源汇点。$E $中的每条边 $ (u, v)$ 都…

金砖技能大赛-内存取证

检材链接 :https://pan.baidu.com/s/1tYgIicCqJExmaMLYa3YeSA 提取码:lulu按照惯例先打印出信息 1.从内存中获取到用户admin的密码并且破解密码,以Flag{admin,password} 形式提交(密码为 6 位); 先使用lsadump指令看看python2 vol.py -f /文件路径/文件 hashdump最后一个是…

script 标签放在 HTML 文档的 body 内底部

以下是将 <script> 标签放在 HTML 文档的 <body> 内底部的几个重要原因: 1. 页面加载顺序和性能优化原理:当浏览器解析 HTML 文档时,它会按顺序执行遇到的元素。如果 <script> 标签位于 <head> 中或 <body> 的顶部,浏览器会在下载和执行脚本…

折腾笔记[4]-cuda的hello-world

在window11上搭建cuda开发环境并编译hello world程序;摘要 在window11上搭建cuda开发环境并编译hello world程序; 关键信息编译器:cuda nvcc 12.4.131 平台:windows11原理简介 cuda简介 CUDA(Compute Unified Device Architecture,统一计算架构)是由英伟达所推出的一种集成技术…

13. 滑块控件

一、抽象滑块QScrollBar、QSlider 和 QDail 都是从 QAbstractSlider 类继承而来的,因此它们的多数方法是相同的。我们可以在终端中使用 pip 安装 pyside6 模块。 pip install pyside6QAbstractSlider 类的常用方法如下: # 实例方法 orientation() -> Qt.Orientation …

3.数据类型

3.1字符串1.正常字符串使用 或 "" 包裹起来2.注意转义字符 \ \ 显示’ \n 换行 \t tab \u4e2d \u### Unicode字符3.多行字符串编写 4.模板字符串5.字符串长度 str(变量名).length6.字符串的可变性,不可变String Buffer和StringBuilder都是可变的,String…

h5如何解决移动端适配问题

使用响应式布局(Responsive Layout)原理:通过CSS媒体查询(Media Queries)根据设备的屏幕尺寸、分辨率等属性来动态调整页面的布局和样式。媒体查询允许您针对不同的媒体类型(如屏幕、打印等)和条件(如屏幕宽度、高度、设备方向等)应用不同的CSS规则。 示例代码:例如,…

第15章 流与IO

第15章 流与IO 15.1 .NET 流的架构 .NET 流的架构主要包含三个概念:** 后台存储 、 装饰器 以及 流适配器 **,如图所示: C7.0 核心技术指南 第7版.pdf - p655 - C7.0 核心技术指南 第 7 版-P655-20240216192328 ​​ 其中** 后台存储 和 装饰器 **为流。后台存储流:负责处理…

超全性能调优标准制定指南,你一定不能错过!

0 前言 我有个朋友说他们国企的系统从未性能调优,功能测试完就上线,线上也没性能问题,何必还做性能调优? 本文搞清:为什么要做性能调优? 啥时开始做? 做性能调优是不是有标准?1 为啥做性能调优?有些性能问题是慢慢产生,到了时间就自爆 更多性能问题是由访问量波动导致…