算法模板整理

常用板子

1.并查集

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#define maxn 5003
using namespace std;

int fa[maxn],n,m,p,a,b;

int find(int x)
{
	if(fa[x]!=x){
		fa[x]=find(fa[x]);
	}
	return fa[x];
}

void hb(int x,int y)
{
	fa[x]=y;
}

int main()
{
	scanf("%d%d%d",&n,&m,&p);
    
	for(int i=0;i<=n;i++) fa[i]=i;
    
	for(int i=1;i<=m;i++)
	{
		cin>>a>>b;
		int r1=find(a);
		int r2=find(b);
		if(r1!=r2) hb(r1,r2);
	}
	
	for(int i=1;i<=p;i++)
	{
		cin>>a>>b;
		int r1=find(a);
		int r2=find(b);
		if(r1==r2) cout<<"Yes"<<endl;
		else cout<<"No"<<endl;
	}
	
	return 0;
}

2.SPFA(单源最短路)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#define INF 0x7fffffff
#define maxn 10000+4
#define maxm 500000+5
using namespace std;

struct edge{
	int to,dis,nxt;
}e[maxm];

int num=0,h[maxn];
void add(int from,int to,int dis)
{
	e[++num].nxt=h[from];
	e[num].dis=dis;
	e[num].to=to;
	h[from]=num;
	return ;
}

int q[maxm],l[maxn],head=0,tail=0,n,m,s;
bool vis[maxn];
void spfa()
{
	vis[s]=1;q[++tail]=s;l[s]=0;
	while(head<tail){
		int j=q[++head];
		vis[j]=0;
		int p=h[j];
		while(p){
			int to=e[p].to;
			if(l[to]>l[j]+e[p].dis){
				l[to]=l[j]+e[p].dis;
				if(vis[to]==0){
					vis[to]=1;
					q[++tail]=to;
				}
			}
			p=e[p].nxt;
		} 
	}
	return ;
}

int main()
{
	cin>>n>>m>>s;
	for(int i=1;i<=n;i++) l[i]=INF;
	memset(vis,0,sizeof(vis));
	memset(h,0,sizeof(h));
	
	for(int i=1,u,v,w;i<=m;i++)
	{
		scanf("%d%d%d",&u,&v,&w);
		add(u,v,w);
	}
	spfa();
	for(int i=1;i<=n;i++)
	{
		printf("%d ",l[i]);
	}

	return 0;
}


3.线段树

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#define maxn 100005
#define LL long long
#define ls l,mid,rt<<1
#define rs mid+1,r,rt<<1|1
using namespace std;

LL sum[maxn<<2],add[maxn<<2];

void putdown(int rt,int len)
{
	LL y=add[rt];
	if(y){
		add[rt<<1]+=y;
		add[rt<<1|1]+=y;
		sum[rt<<1]+=(y*(len-(len>>1)));
		sum[rt<<1|1]+=(y*(len>>1));
		add[rt]=0;
	}
	return ;
}

void getup(int rt)
{
	sum[rt]=sum[rt<<1]+sum[rt<<1|1];
	return ;
}

void update(int L,int R,int c,int l,int r,int rt)
{
	if(L<=l&&r<=R){
		add[rt]+=c;
		sum[rt]+=(c*(r-l+1));
		return ;
	}
	int mid=(l+r)>>1;
	putdown(rt,r-l+1);
	if(L<=mid) update(L,R,c,ls);
	if(mid<R) update(L,R,c,rs);
	getup(rt);
	return ;
}

LL query(int L,int R,int l,int r,int rt)
{
	if(L<=l&&r<=R){
		return sum[rt];
	}
	int mid=(l+r)>>1;
	LL t=0;
	putdown(rt,r-l+1);
	if(L<=mid) t+=query(L,R,ls);
	if(mid<R) t+=query(L,R,rs);
	return t;
}


int main()
{
	int n,m;
	cin>>n>>m;
	for(int i=1,k;i<=n;i++)
	{
		scanf("%d",&k);
		update(i,i,k,1,n,1);
	}
	for(int i=1,x,y,k,q;i<=m;i++)
	{
		scanf("%d",&q);
		if(q==1){
			scanf("%d%d%d",&x,&y,&k);
			update(x,y,k,1,n,1);
		}
		if(q==2){
			scanf("%d%d",&x,&y);
			LL ans=query(x,y,1,n,1);
			printf("%lld\n",ans);
		}
	}

	return 0;
}


5.快速幂

#include <iostream>
#include <cstdio>
#include <cmath>
#define LL long long
using namespace std;
LL b,k,p;
LL ksm(LL a,LL x)
{
	LL ans=1;
	while(x){
		if(x&1) ans=ans*a%k;
		a=a*a%k;
		x>>=1;
	}
	return ans;
}
int main()
{
	cin>>b>>p>>k;
	printf("%lld^%lld mod %lld=%lld",b,p,k,ksm(b,p)%k);
	return 0;
}

6.最小生成树

#include <iostream>
#include <cstdio>
#include <algorithm>
#define maxn 5000+5
#define maxm 200000+5
using namespace std;
int n,m,fa[maxn],sum=0,ans=0;
struct E{
	int u,v,w;
}e[maxm];
int find(int x)
{
	if(fa[x]!=x) fa[x]=find(fa[x]);
	return fa[x];
}
void hb(int x,int y)
{
	fa[find(x)]=find(y);
}
bool cmp(E x,E y)
{
	return x.w<y.w;
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=m;i++)
	scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
	sort(e+1,e+1+m,cmp);
	for(int i=1;i<=n;i++) fa[i]=i;
	for(int i=1;i<=m;i++)
	{
		int a=find(e[i].u),b=find(e[i].v),c=e[i].w;
		if(a!=b){
			hb(a,b);
			sum++;
			ans+=c;
		}
		if(sum==n-1) break;
	}
	cout<<ans;
	return 0;
}

7.最大公约数(gcd)+快读

#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cstdio>
#include <queue>
#include <vector>
#include <cmath>
#include <cstdlib>
#include <ctime>
#define maxn 200000+5
using namespace std;
int n,m,p,q;
inline int read(){
    int x=0;char ch=getchar();
    if(ch>'9'||ch<'0') ch=getchar();
    while(ch<='9'&&ch>='0'){
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x;
}
int gcd(int a,int b)
{
	return b==0?a:gcd(b,a%b);
}
int main (){
	n=read();m=read();
	int nm=n*m,sum=0;
	for(int i=n;i<=m;i++)
	{
		for(int j=n;j<=m;j++)
		{
			if(i*j==nm&&gcd(i,j)==n){
			sum++;//cout<<i<<" "<<j<<endl;	
			} 
		}
	}
	cout<<sum;

	return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值