倍增

news/2025/12/9 0:14:25/文章来源:https://www.cnblogs.com/Atserckcn/p/19324045

倍增

定义

倍增是一种与二分相似的算法,但是把二进制摆在了明面上。

大体思路是一步步确定答案的二进制表示的每一位。

简单倍增

例题:洛谷 P2249 【深基13.例1】查找

你说得对,但是这题其实是二分模板题。

首先转化为找到第一个小于 \(q\) 的位置 \(p\)

因为长度不大于 \(10^6\),所以答案一定可以用一个二十位二进制数来表示,因为 \(2^{20}>10^6\)

然后我们就尝试从高到低确定这个答案的每一位。

显然对于从低到高第 \(i\) 位,数值是 \(2^{i}\),其中 \(i\ge 0\)

那么我们判断,如果 \(2^i\le n\land a_{p_{i}}<q\),那么说明答案的第 \(i\) 位一定是一。

因为如果这一位不是一,那么就算后面所有的二进制位都是 \(1\),总和也没有 \(2^{i}\) 大,是更到不了 \(a_{ans}\) 的。

如果 \(a_{p_i}\ge q\),说明跳太大了,这一位是 \(0\)

简言之,二分是通过检查 mid 的可行性,而倍增是通过 check 每个二进制位的可行性。

以此类推,直到找到答案为止。

最后要记得特判是否越界。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ljl;
#define FUP(i,x,y) for(int i=(x);i<=(y);++i)
#define FDW(i,x,y) for(int i=(x);i>=(y);--i)
const int N=1e6+5;
int n,q,a[N],x;void Main()
{int p=0;cin>>x;FDW(i,20,0){if((p|(1<<i))<=n&&a[p|(1<<i)]<x)p=p|(1<<i);}if(p<n&&a[p+1]==x)cout<<p+1<<' ';else cout<<"-1 ";return;
}
int main(){ios::sync_with_stdio(0);cin>>n>>q;FUP(i,1,n)cin>>a[i];while(q--)Main();cout<<'\n'; return 0;
}

对于倍增的感性理解

首先我们知道,对于任意一个整数都可以分解成二进制的形式。

那么假设我们开了挂,知道了答案,那么这个答案 \(ans\) 也是由一位位的二进制数表达的。

那么我们就可以尝试跳步子。

第一次跳足够长,如果超出了,就撤回这一步,尝试更小的步子。

如果没超过,就迈出去。

这样迈出去对应 \(1\),撤回对应 \(0\),总可以凑成 \(ans\)

树上倍增

因为倍增的结构相对稳定,那么就可以在多个数据结构上使用,就比如树。

举个例子,LCA!

Luogu P3379 【模板】最近公共祖先(LCA)

那么在树上,我们该怎么维护呢?

首先二分显然不太好搞。因为无法快速求出两点之间的中点。

我们考虑递推。

\(f_{i,j}\) 表示从 \(i\) 出发,跳了 \(2^j\) 步所到达的点。

那么显然有 \(f_{i,j}=f_{f_{i,j-1},j-1}\),即在 \(i\) 上先跳 \(2^{j-1}\) 步,再跳 \(2^{j-1}\) 步的结果。

因为 \(2^j=2^{j-1}+2^{j-1}\)

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=5e5+5,M=N;
int n,q,s,cnt_e,ehead[N],fa[N][25],dep[N];
struct E{int to,pre;
}e[M<<1];
void adde(int from,int to)
{e[++cnt_e].to=to;e[cnt_e].pre=ehead[from];ehead[from]=cnt_e;return;
}
void dfs(int u,int uf)
{fa[u][0]=uf;dep[u]=dep[uf]+1;for(int i=1;i<=20;++i)fa[u][i]=fa[fa[u][i-1]][i-1];for(int i=ehead[u];i;i=e[i].pre){int v=e[i].to;if(v==uf)continue;dfs(v,u);}return;
}
int getlca(int x,int y)
{if(x==y)return x;if(dep[x]<dep[y])swap(x,y);for(int i=20;i>=0;--i)if(dep[x]-(1<<i)>=dep[y])x=fa[x][i];if(x==y)return x;for(int i=20;i>=0;--i){if(fa[x][i]!=0&&fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];}return fa[x][0];
}
int main(){
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);cin>>n>>q>>s;for(int i=1,u,v;i<n;++i){cin>>u>>v;adde(u,v);adde(v,u);}dfs(s,0);while(q--){int u,v;cin>>u>>v;cout<<getlca(u,v)<<'\n';}return 0;
}

同理,树上倍增不仅可以维护祖先,还可以顺便维护一些链信息。

比如用 \(m_{i,j}\) 表示从 \(i\) 出发,跳 \(2^j\) 步的过程中,所有节点的权值最大值。

那么状态转移方程也大差不差:\(m_{i,j}=\max\left\{m_{i,j-1},m_{f_{i,{j-1}},j-1}\right\}\)

未知上界

如题,就是一种上界未知的二分。

其实说是未知,但毕竟是有答案的,所以上界也是有的。

现在讨论的是如何快速确定上界,即算法本身不依赖于上界,时间复杂度为 \(\log ans\)

还是用二进制玩。

我们从小到大枚举 \(i\),check 一下 \(2^i\) 可不可行。如果没跳过就跳。

如果跳过了,假设 \(2^t\) 时超过答案。

那么答案就被确定在了 \([2^{t-1},2^t)\),然后再从 \(t-1\)\(0\) 枚举 \(j\),按照之前说的倍增方法一步一步确定答案即可。

总结:先逐渐扩大步长,够用了后再一步步缩短步长。也就是只有锁定第一步时是从小到大,其他都是从大到小。

优势:不依赖总大小,只依赖于答案。

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

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

相关文章

pwn入门记录

x86 x64 c语言栈的格式 ASLR PIE Canary NX 保护 RELRO保护 例题 ret2text ret2shellcode pwntools教程 shellcraft asm ida动态远程调试virtualbox ubuntu上的elf,获取栈的地址 ROP gadget黄粱一梦,终是一空本文来自…

2025-12-9

2025-12-9深度工作锻炼身体去掉不必要的娱乐、无聊时可以冥想戒撸必须自我觉醒,自我救赎,才能得到人身与精神上的自我解放!

Maven 下载 Spigot 依赖失败问题排查:Could not find artifact org.spigotmc:spigot-api…

🔧 Maven 下载 Spigot 依赖失败问题排查:Could not find artifact org.spigotmc:spigot-api… 在使用 Maven 开发 Minecraft 插件时,我遇到了一个依赖无法下载的问题。 项目中引入了 Spigot API: <dependency&…

Maven 下载 Spigot 依赖失败问题排查:Could not find artifact org.spigotmc:spigot-api…

🔧 Maven 下载 Spigot 依赖失败问题排查:Could not find artifact org.spigotmc:spigot-api… 在使用 Maven 开发 Minecraft 插件时,我遇到了一个依赖无法下载的问题。 项目中引入了 Spigot API: <dependency&…

12.8每日总结

今日的主要课程有软件需求分析,大型数据库技术以及物联网工程,软件需求分析进行了小测,系统页面搭建成功了,但是数据库连接还是有点问题,因为子页面和对应功能比较复杂,12周以后课变少了,加油把驾照拿下

2025/12/08 分享

续接昨天的讨论,昨天的引理 1 和引理 4 后面看了一下发现是同一个定理,无伤大雅 一: 首先讨论提到的 GESP202509L8T2 :对于一个带权稀疏连通图 \(G = (V, E)\) ,询问每条边从 \(G\) 中删除后得到的图 \(G^{}\) 中…

frp

docker hub地址: https://hub.docker.com/r/snowdreamtech/frpc docker run --restart=always --network host -d -v /etc/frp/frps.toml:/etc/frp/frps.toml --name frps snowdreamtech/frps:alpine

深刻理解HTTP和RPC的区别

首先,HTTP它本质上是一个协议,它是互联网数据通信的基础,定义了一套如何在网络上交换超文本的一个规则。它的核心就是资源和状态。比如说我们用get去获取一个用户资源,用put去更新它。而RPC本质是一种编程范式,或…

linux 中 socket 文件是什么?和 socket 编程有什么关系?和 TCP/IP 协议栈又有什么关系?

linux 中 socket 文件是什么?和 socket 编程有什么关系?和 TCP/IP 协议栈又有什么关系?要理解 linux 中的 socket 文件,以及什么是socket 编程,首先需要知道两个知识点: 1、什么是进程,进程名又是什么? 2、进程…

智能座舱的下一站:从“车内大屏”到“全域协同” - 智慧园区

就在10年前,车里能有一块彩色屏幕,就足以被称作“高科技”了。时至今日,智能座舱已然成为新能源汽车比拼的核心战场。然而,行业的竞争似乎走入了一个怪圈:比谁的屏幕更多、更大、更炫。当我们冷静下来思考,智能座…

硬件电子知识(基础篇)

电子元器件 电阻:核心功能:通过自身特性限制电流流动,实现电压分配,消耗电能 具体功能: 限流:LED串联电阻防止电流过大烧毁 分压:模拟电路中拆分电压信号(如传感器输出分压采样) 负载:替代实际负载进行电路调…

每日的小开心

今天课堂上的团队战意外拿到第二名,因为前面的队冒险主义失误了,我们保守主义难得不是第三名,可以多一些课堂分!还有宿舍一起打边炉,可能是我们最后一次了,毕业以后可能很难有时间聚一聚。 今天还吃了个大瓜

揭秘业务逻辑滥用:API安全中“利用游戏规则”的攻击手法

本文深入探讨了API安全中的业务逻辑滥用攻击。它解释了攻击者如何利用API的预期功能逻辑而非技术漏洞,通过绕过支付步骤、操控数据等方式实施攻击,并介绍了Wallarm平台如何通过行为异常检测和规范执行等高级技术进行…

揭秘业务逻辑滥用:API安全中“利用游戏规则”的攻击手法

本文深入探讨了API安全中的业务逻辑滥用攻击。它解释了攻击者如何利用API的预期功能逻辑而非技术漏洞,通过绕过支付步骤、操控数据等方式实施攻击,并介绍了Wallarm平台如何通过行为异常检测和规范执行等高级技术进行…

放弃原容器建立新容器,保存留数据卷且映射

一.以mysql容器为例子1.sudo mkdir -p /home/mysql_data #创建新文件夹2.sudo chown -R 999:999 /home/mysql_data # 将目录所有权设为MySQL容器内使用的用户(通常是999:999) 将 /home/mysql_data 目录及其内部所有…

CommonUI-学习记录

UE官方教程 CommonUI重要特点Common UI 本质上来说就是把UI当成栈,你可以push不同的widget到不同的栈上面。然后栈本身又会存到栈里面,显示最上层的栈元素所包含的元素The Viewport is the base for all input routi…

银行反欺诈day1

1.银行反欺诈系统都运行在那些场景? 区分为实时交易监控和事后分析场景类型 具体场景 风险特征实时交易拦截 网银/手机银行转账POS刷卡消费ATM取现第三方支付(如支付宝/微信快捷支付)开放银行API调用(如代扣) 毫秒…

2025年数控折弯机模具选购参考

在当前钣金加工行业,客户对数控折弯机模具的采购决策日益聚焦于高性价比与价格透明化。随着市场竞争加剧和终端用户成本控制意识增强,模具供应商不仅需提供稳定可靠的品质,还需在价格策略上展现清晰、合理且具竞争力…

Hikvision 考勤机数据提取(3)

同样使用 HTTPDigestAuth import json import binascii import base64 import hashlib import time import requests import argparse import uuid import xml.etree.ElementTree as ET from datetime import datetime…

Hikvision 考勤机数据提取(3)

同样使用 HTTPDigestAuth import json import binascii import base64 import hashlib import time import requests import argparse import uuid import xml.etree.ElementTree as ET from datetime import datetime…