Templates by Hanggoash

整数二分

边界条件处理不好非常容易写挂
以简单的二分查找为例,有以下两种写法

点击查看代码
int bsearch(int x,int l,int r)
{
if(l>=r)return l;
int mid=l+r>>1;
if(a[mid]<x)return bsearch(x,mid+1,r);
else return bsearch(x,l,mid);
}
点击查看代码
int bsearch(int x,int l,int r)
{
if(l>=r)return l;
int mid=(l+r+1)>>1;
if(a[mid]<=x)return bsearch(x,mid,r);
else return bsearch(x,l,mid-1);
}

简单来说,首先需要知道计算 mid 的时候是下取整的。
判断条件中取等号的那个需要保留 mid ,因此这时 mid=(l+r+1)>>1 ,防止当查询右子区间长度为 1 的时候造成死循环,例如 [2,3]

如果需要取等的一边在左子区间,那就不需要 ,因为会被下取整,不取等号不需要保留,所以直接 +1

快速幂

点击查看代码
inline int power(int a,int b,int p)
{
long long ans=1;
while(b)
{
if(b&1)ans=ans*a%p;
a=a*a%p;
b>>=1;
}
return ans;
}

线段树

1

点击查看代码

矩阵快速幂

点击查看代码

LCA

倍增

点击查看代码

树链剖分

最短路

Dijkstra

点击查看代码
inline void dijkstra(int s)
{
priority_queue< pair<int,int> > q;
memset(dis,0x3f,sizeof dis);
memset(vis,0,sizeof vis);
dis[s]=0,q.push(make_pair(0,s));
while(q.size())
{
int x=q.top().second;q.pop();
if(vis[x])continue;
vis[x]=1;
for(int i=head[x];i;i=E[i].nex)
{
int v=E[i].v;
if(dis[v]>dis[x]+E[i].w)
{
dis[v]=dis[x]+E[i].w;
if(!vis[v])q.push(make_pair(-dis[v],v));
}
}
}
}

可以用堆进行优化,默认大根堆,直接push(-dis[v],v)就好了
DJ的本质就是贪心,vis 数组代表有没有被松弛过,每个点只会被松弛一次就能算出正确值。

SPFA

点击查看代码
inline void spfa(int x)
{
queue<int>q;
memset(dis,0x7f,sizeof dis);
memset(vis,0,sizeof vis);
q.push(x);vis[x]=1;dis[x]=0;
while(!q.empty())
{
int x=q.front();vis[x]=0,q.pop();
for(int i=head[x];i;i=E[i].nex)
{
int v=E[i].v;
if(dis[x]+E[i].w<dis[v])
{
dis[v]=dis[x]+E[i].w;
if(!vis[x])q.push(v),vis[v]=1;
}
}
}
}

注意spfa的vis数组代表是否在队列中,可以经过多次修改;而dij的vis数组代表是否松弛过,只会被修改一次

posted @   Hanggoash  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
动态线条
动态线条end
点击右上角即可分享
微信分享提示