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  阅读(6)  评论(0编辑  收藏  举报
动态线条
动态线条end
点击右上角即可分享
微信分享提示