模板总结

〇、常用头文件总结

前4项第一个字符:i c a i(我看见了一个我)
第5项全称:cstring(一个字符串飘过)
后4项最后一个字符:b h e s(不好意思)
至于其他STL,要用什么就加什么。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<iomanip>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<cctype>
#include<climits>

一、输入输出优化

(一)输入优化

int in(){
	int f=1,x=0;
	char ch=getchar();
	while(!isdigit(ch)){
		if(ch=='-')f=-1;
		ch=getchar();
	}
	while(isdigit(ch)){
		x=(x<<3)+(x<<1)+ch-'0';
		ch=getchar();
	}
	return f*x;
}

(二)输出优化

void out(int x){
	if(x<0){
		putchar('-');
		x=-x;
	}
	if(x>=10)out(x/10);
	putchar(x%10+'0');
}

二、基本算法

(一)二分答案

int work(){
	int L=1,R=n;
	while(L<R){
		int M=L+R>>1;
		if(check())R=M;
		else L=M+1;
	}
	return L;
}

(二)排序

1.离散化

void lsh(){
	for(int i=1;i<=n;i++)tmp[i]=a[i];
	sort(tmp+1,tmp+1+n);
	int m=unique(tmp+1,tmp+1+n)-tmp-1;
	for(int i=1;i<=n;i++)a[i]=lower_bound(tmp+1,tmp+1+n,a[i])-tmp;
	//此时a数组保存的是原来的数被离散化后的数 
}

2.归并排序

void merge(int l,int r){
	if(l==r)return;
	int m=l+r>>1,i=l,j=m+1,k=l;
	merge(l,m);
	merge(m+1,r);
	while(i<=m&&j<=r){
		if(a[i]<=a[j])b[k++]=a[i++];
		else b[k++]=a[j++];//cnt+=m-i+1
	}
	while(i<=m)b[k++]=a[i++];
	while(j<=r)b[k++]=a[j++];
	for(k=l;k<=r;k++)a[k]=b[k];
} 

(三)倍增

1.ST算法

(1)预处理
void init(){
	int t=log2(n)+1;
	for(int i=1;i<=n;i++)maxx[i][0]=a[i];
	for(int j=1;j<t;j++){
		for(int i=1;i+(1<<j)-1<=n;i++){
			maxx[i][j]=max(maxx[i][j-1],maxx[i+(1<<(j-1))][j-1]);
		}
	}
}
(2)查询
int ask(int l,int r){
	int k=log2(r-l+1);
	return max(maxx[l][k],maxx[r-(1<<k)+1][k]);
}

三、基本数据结构

(一)Hash

1.Hash表

int check(int x){
	int tmp=x%mod;
	for(int i=0;i<hash[tmp].size();i++){
		if(hash[tmp][i]==x)return 1;
	}
	hash[tmp].push_back(x);
	return 0;
}

2.字符串Hash

int p,mod;
int hash(char *s){
	int len=strlen(s+1),ans=0;
	for(int i=1;i<=len;i++)ans=(ans*p+s[i])%mod;
	return ans;
}

(二)Trie

1.插入

void insert(char *s){
	int len=strlen(s),p=1;
	for(int i=0;i<len;i++){
		int ch=s[i]-'a';
		if(!trie[p][ch])trie[p][ch]=++cnt;
		p=trie[p][ch];
	}
	end[p]=1;
}

2.查询

int search(char *s){
	int len=strlen(s),p=1;
	for(int i=0;i<len;i++){
		int ch=s[i]-'a';
		p=trie[p][ch];
		if(!p)return 0;
	}
	return end[p];
}

四、数论

(一)筛法

1.埃氏筛法

(1)初始化
void init(){
	for(int i=2;i<=n;i++){
		if(vis[i])continue;
		for(int j=i;j<=n/i;j++)vis[i*j]=1;
	}
}
(2)查询
int isprime(int x){
	return !vis[x];
}

(二)费马小定理

1.求逆元

(1)快速幂
int Pow(int a,int b){
	int ans=1;
	while(b){
		if(b&1)ans=ans*a%mod;
		a=a*a%mod;
		b>>=1;
	}
	return ans;
}
(2)查询
int ny(int x){
	return Pow(x,mod-2);
}

(三)扩展欧几里得

int x,y;
void exgcd(int a,int b){
	if(!b){
		x=1,y=0;
		return;
	}
	exgcd(b,a%b);
	int t=x;
	x=y,y=t-a/b*y;
}
//此时x和y是方程的一组特解
//ax+by=c的通解是x=c/gcd*x0+k*b/d,y=c/gcd*y0+k*a/d(k∈Z)此处x0和y0是exgcd得到的特解

(四)矩阵乘法

(五)卡特兰数

1.初始化

void init(){
	f[0][0]=1;
	for(int i=1;i<=n;i++){
		f[i][0]=1;
		for(int j=1;j<=i;j++)f[i][j]=f[i-1][j-1]+f[i-1][j];
	}
}

2.查询

int ask(int x){
	return f[2*x][x]/(x+1);
}

(六)高精度

1.加法

string Add(string A,string B){
	int la=A.size(),lb=B.size(),lc=1,a[100005],b[100005],c[100005],x=0;
	for(int i=0;i<la;i++)a[la-i]=A[i]-'0';
	for(int i=0;i<lb;i++)b[lb-i]=B[i]-'0';
	while(lc<=la||lc<=lb){
		c[lc]=a[lc]+b[lc]+x;
		x=c[lc]/10;
		c[lc]%=10;
		lc++;
	}
	c[lc]=x;
	while(!c[lc]&&lc>1)lc--;
	string ans;
	for(int i=lc;i>=1;i--)ans+=c[i]+'0';
	return ans;
}

2.减法

string Minus(string A,string B){
	int la=A.size(),lb=B.size(),lc=1,a[100005],b[100005],c[100005];
	if(la<lb||la==lb&&A<B){
		string tmp;
		tmp=A;
		A=B;
		B=tmp;
	}
	la=A.size(),lb=B.size();
	for(int i=0;i<la;i++)a[la-i]=A[i]-'0';
	for(int i=0;i<lb;i++)b[lb-i]=B[i]-'0';
	while(lc<=la){
		if(a[lc]<b[lc])a[lc]+=10,a[lc+1]--;
		c[lc]=a[lc]-b[lc];
		lc++;
	}
	while(!c[lc]&&lc>1)lc--;
	string ans;
	for(int i=lc;i>=1;i--)ans+=c[i]+'0';
	return ans;
}

3.乘法

string Mul(string A,string B){
	int la=A.size(),lb=B.size(),lc=la+lb,a[10005],b[10005],c[10005],x=0;
	for(int i=0;i<la;i++)a[la-i]=A[i]-'0';
	for(int i=0;i<lb;i++)b[lb-i]=B[i]-'0';
	for(int i=1;i<=la;i++){
		x=0;
		for(int j=1;j<=lb;j++){
			c[i+j-1]+=a[i]*b[j]+x;
			x=c[i+j-1]/10;
			c[i+j-1]%=10;
		}
		c[i+lb]=x;
	}
	while(!c[lc]&&lc>1)lc--;
	string ans;
	for(int i=lc;i>=1;i--)ans+=c[i]+'0';
	return ans;
}

4.除法

string Div(string A,int b){
	int la=A.size(),lc=1,a[10005],c[10005],x=0;
	for(int i=0;i<la;i++)a[i+1]=A[i]-'0';
	while(lc<=la){
		c[lc]=(x*10+a[lc])/b;
		x=(x*10+a[lc])%b;
		lc++;
	}
	lc=1;
	while(!c[lc]&&lc<la)lc++;
	string ans;
	for(int i=lc;i<=la;i++)ans+=c[i]+'0';
	return ans;
}

五、数据结构进阶

(一)并查集

1.初始化

void init(){
	for(int i=1;i<=n;i++)fa[i]=i;
}

2.查询

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

3.合并

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

(二)树状数组

(三)线段树

(四)分块

六、动态规划

(一)求子树节点数

1.预处理

void dfs(int u,int fa){
	size[u]++;
	for(int i=head[u];i;i=Next[i]){
		int v=to[i];
		if(fa==v)continue;
		dfs(v,u);
		size[u]+=size[v];
	}
}

2.查询

int ask(int x){
	return size[x];
}

七、图论

(一)最短路

1.Floyd

void floyd(){
	for(int k=1;k<=n;k++){
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				if(k!=i&&k!=j&&i!=j){
					f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
				}
			}
		}
	}
}

2.Dijkstra

void dijkstra(int x){
	memset(dis,0x3f,sizeof dis);
	memset(vis,0,sizeof vis);
	dis[x]=0;
	priority_queue<pair<int,int> > q;
	q.push(make_pair(0,x));
	while(q.size()){
		int u=q.top().second;
		q.pop();
		if(vis[u])continue;
		vis[u]=1;
		for(int i=head[u];i;i=Next[i]){
			int v=to[i],w=wei[i];
			if(dis[v]>dis[u]+w){
				dis[v]=dis[u]+w;
				q.push(make_pair(-dis[v],v));
			}
		}
	}
}

3.SPFA

void spfa(int x){
	memset(dis,0x3f,sizeof dis);
	memset(vis,0,sizeof vis);
	vis[x]=1;
	dis[x]=0;
	queue<int> q;
	q.push(x);
	while(q.size()){
		int u=q.front();
		q.pop();
		vis[u]=0;
		for(int i=head[u];i;i=Next[i]){
			int v=to[i],w=wei[i];
			if(dis[v]>dis[u]+w){
				dis[v]=dis[u]+w;
				if(!vis[v]){
					vis[v]=1;
					q.push(v);
				}
			}
		}
	}
}

(二)最小生成树

1.Kruskal

int get(int x){
	if(x==fa[x])return x;
	return fa[x]=get(fa[x]);
}
int kruskal(){
	int ans=0;
	sort(a+1,a+1+m);
	for(int i=1;i<=n;i++)fa[i]=i;
	for(int i=1;i<=m;i++){
		int x=get(a[i].u),y=get(a[i].v);
		if(x==y)continue;
		fa[x]=y;
		ans+=a[i].w;
	}
	return ans;
}

(三)最近公共祖先

1.初始化

void bfs(int x){
	dep[x]=0;
	queue<int> q;
	q.push(x);
	while(q.size()){
		int u=q.front();
		q.pop();
		for(int i=head[u];i;i=next[i]){
			int v=to[i];
			if(dep[v])continue;
			dep[v]=dep[u]+1;
			f[v][0]=u;
			for(int j=1;j<=t;j++)f[v][j]=f[f[v][j-1]][j-1];
			q.push(v);
		}
	}
}

2.查询

int lca(int u,int v){
	if(dep[u]>dep[v])swap(u,v);
	for(int i=t;i>=1;i--){
		if(dep[f[v][i]]>=dep[u])v=f[v][i];
	}
	if(x==y)return x;
	for(int i=t;i>=1;i--){
		if(f[u][i]!=f[f][i]){
			u=f[u][i];
			v=f[v][i];
		}
	}
	return f[u][0];
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值