注意:
本文章只对蓝桥杯可能用到的算法模板,借助算法基础课的内容进行简单整理,不涉及算法原理及推导证明。
快速排序
#include<bits/stdc++.h>
using namespace std;
const int N=100010;
int a[N];
int n;
void quick_sort(int a[],int l,int r){
if(l>=r) return; //递归出口
int i=l-1,j=r+1;
int x=a[(l+r)/2];
while(i<j){
do i++; while(a[i]<x);
do j--; while(a[j]>x);
if(i<j) swap(a[i],a[j]);
}
quick_sort(a,l,j);
quick_sort(a,j+1,r);
}
int main(){
scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%d",&a[i]);
quick_sort(a,0,n-1);
for(int i=0;i<n;i++) printf("%d ",a[i]);
return 0;
}
归并排序
#include<iostream>
using namespace std;
const int N=100010;
int a[N],tmp[N];
int n;
void merge_sort(int a[],int l,int r){
if(l>=r) return;
int mid=(l+r)/2;
merge_sort(a,l,mid),merge_sort(a,mid+1,r);
int i=l,j=mid+1,k=0;
while(i<=mid&&j<=r){
if(a[i]<a[j]) tmp[k++]=a[i++];
else tmp[k++]=a[j++];
}
while(i<=mid) tmp[k++]=a[i++];
while(j<=r) tmp[k++]=a[j++];
for(int i=l,j=0;i<=r;i++,j++) a[i]=tmp[j];
}
int main(){
scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%d",&a[i]);
merge_sort(a,0,n-1);
for(int i=0;i<n;i++) printf("%d ",a[i]);
return 0;
}
整数二分(数的范围)
#include<iostream>
using namespace std;
const int N=100010;
int a[N];
int n,q,k;
int main(){
scanf("%d%d",&n,&q);
for(int i=0;i<n;i++) scanf("%d",&a[i]);
while(q--){
int x;
scanf("%d",&x);
int l=0,r=n-1;
while(l<r){
int mid=(l+r)/2;
if(a[mid]>=x) r=mid;
else l=mid+1;
}
if(a[l]!=x) printf("-1 ");
else printf("%d ",l);
l=0,r=n-1;
while(l<r){
int mid=(l+r+1)/2;
if(a[mid]<=x) l=mid;
else r=mid-1;
}
if(a[l]!=x) printf("-1\n");
else printf("%d\n",l);
}
return 0;
}
一维前缀和
#include<iostream>
using namespace std;
const int N=100010;
int s[N];
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&s[i]);
for(int i=1;i<=n;i++) s[i]+=s[i-1];
while(m--){
int l,r;
scanf("%d%d",&l,&r);
printf("%d\n",s[r]-s[l-1]);
}
return 0;
}
二维前缀和(借助画图分析)
#include<iostream>
using namespace std;
const int N=1010;
int a[N][N];
int s[N][N];
int n,m,q;
int main(){
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%d",&a[i][j]);
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j];
}
}
while(q--){
int x1,y1,x2,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
printf("%d\n",s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1]);
}
}
一维差分
#include<iostream>
using namespace std;
const int N=100010;
int a[N],b[N];
int n,m;
void insert(int l,int r,int c){
b[l]+=c;
b[r+1]-=c;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
insert(i,i,a[i]);
}
while(m--){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
insert(a,b,c);
}
for(int i=1;i<=n;i++) a[i]=a[i-1]+b[i];
for(int i=1;i<=n;i++) printf("%d ",a[i]);
return 0;
}
差分矩阵(重点复习)
#include<iostream>
using namespace std;
const int N=1010;
int a[N][N],b[N][N];
int n,m,q;
void insert(int x1,int y1,int x2,int y2,int c){
b[x1][y1]+=c;
b[x1][y2+1]-=c;
b[x2+1][y1]-=c;
b[x2+1][y2+1]+=c;
}
int main(){
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%d",&a[i][j]);
insert(i,j,i,j,a[i][j]);
}
}
while(q--){
int x1,y1,x2,y2,c;
scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&c);
insert(x1,y1,x2,y2,c);
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
b[i][j]+=b[i-1][j]+b[i][j-1]-b[i-1][j-1];
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
printf("%d ",b[i][j]);
}
printf("\n");
}
return 0;
}
单调栈
#include<iostream>
#include<stack>
using namespace std;
stack<int> stk;
int n;
int main(){
cin>>n;
for(int i=0;i<n;i++){
int x;
cin>>x;
while(!stk.empty()&&stk.top()>=x) stk.pop();
if(stk.empty()) printf("-1 ");
else printf("%d ",stk.top());
stk.push(x);
}
return 0;
}
滑动窗口
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int a[N];
int n,k;
deque<int> q;
int main(){
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++){
while(q.size()&&q.back()>a[i]) q.pop_back();
q.push_back(a[i]);
if(i-k>=1&&a[i-k]==q.front()){
q.pop_front();
}
if(i>=k){
cout<<q.front()<<" ";
}
}
q.clear();
cout<<endl;
for(int i=1;i<=n;i++){
while(q.size()&&q.back()<a[i]) q.pop_back();
q.push_back(a[i]);
if(i-k>=1&&a[i-k]==q.front()){
q.pop_front();
}
if(i>=k){
cout<<q.front()<<" ";
}
}
return 0;
}
朴素KMP
#include<iostream>
using namespace std;
const int N=1e5+10;
const int M=1e6+10;
char p[N],s[M];
int n,m;
int ne[N];
int main(){
cin>>n>>(p+1)>>m>>(s+1);
for(int i=2,j=0;i<=n;i++){
while(j&&p[i]!=p[j+1]) j=ne[j];
if(p[i]==p[j+1]) j++;
ne[i]=j;
}
for(int i=1,j=0;i<=m;i++){
while(j&&s[i]!=p[j+1]) j=ne[j];
if(s[i]==p[j+1]) j++;
if(j==n){
printf("%d ",i-n);
}
}
return 0;
}
KMP求周期
#include<bits/stdc++.h>
using namespace std;
//s长度为n,s存在最小循环节,最小循环节的长度 n-ne[n],如果存在周期,T=n/(n-ne[n])
const int N=1e6+10;
char p[N];
int ne[N];
int main(){
while(1){
cin>>(p+1);
if(p[1]=='.') break;
int n=strlen(p+1);
for(int i=2,j=0;i<=n;i++){
while(j&&p[i]!=p[j+1]) j=ne[j];
if(p[i]==p[j+1]) j++;
ne[i]=j;
}
if(n%(n-ne[n])==0) printf("%d\n",n/(n-ne[n]));
else printf("1\n");
}
return 0;
}
并查集
#include<iostream>
using namespace std;
const int N=1e5+10;
int p[N];
int n,m;
int find(int x){
if(p[x]!=x) p[x]=find(p[x]);
return p[x];
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) p[i]=i; //初始化,开始之前每个结点指向自己
while(m--){
string s;
int a,b;
cin>>s;
if(s=="M"){
cin>>a>>b;
a=find(a),b=find(b);
if(a!=b){
p[a]=b;
//a的祖先结点不等于b的祖先结点,两者不在一个集合,让a的祖先结点的父节点指向b的祖先
}
}else{
cin>>a>>b;
a=find(a),b=find(b);
if(a==b){
printf("Yes\n");
}else{
printf("No\n");
}
}
}
return 0;
}
BFS
#include<bits/stdc++.h>
using namespace std;
const int N=110;
int g[N][N];
int dis[N][N];
typedef pair<int,int> PII;
#define x first
#define y second
int n,m;
int bfs(PII start,PII end){
memset(dis,-1,sizeof dis);
queue<PII> q;
dis[start.x][start.y]=0;
q.push(start);
while(q.size()){
auto a=q.front();
q.pop();
int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};
for(int i=0;i<4;i++){
int x=a.x+dx[i];
int y=a.y+dy[i];
if(x<1||x>n||y<1||y>m) continue; //越界
if(g[x][y]==1) continue; //障碍
if(dis[x][y]!=-1) continue; //已经被扩展
dis[x][y]=dis[a.x][a.y]+1;
if(x==n&&y==m) return dis[x][y];
q.push({x,y});
}
}
}
int main(){
scanf("%d%d",&n,&m);
PII start,end;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%d",&g[i][j]);
}
}
start={1,1},end={n,m};
int distance=bfs(start,end);
printf("%d",distance);
return 0;
}
朴素迪杰斯特拉求单源最短路
#include<bits/stdc++.h>
using namespace std;
const int N=510;
int g[N][N];
int dis[N];
bool st[N];
int n,m;
int dijkstra(){
memset(dis,0x3f,sizeof dis);
dis[1]=0;
for(int i=0;i<n-1;i++){
int t=-1;
for(int j=1;j<=n;j++){
if(!st[j]&&(t==-1||dis[t]>dis[j])){
t=j;
}
}
for(int j=1;j<=n;j++)
dis[j]=min(dis[j],dis[t]+g[t][j]);
st[t]=1;
}
if(dis[n]==0x3f3f3f3f) return -1;
else return dis[n];
}
int main(){
scanf("%d%d",&n,&m);
memset(g,0x3f,sizeof g);
while(m--){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
g[a][b]=min(g[a][b],c);
}
int distance=dijkstra();
printf("%d",distance);
return 0;
}
弗洛伊德求多源最短路
#include<bits/stdc++.h>
using namespace std;
const int N=210;
const int INF=1e9;
int g[N][N];
int n,m,q;
void floyd(){
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
}
}
}
}
int main(){
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(i==j) g[i][j]=0;
else g[i][j]=INF;
}
}
while(m--){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
g[a][b]=min(g[a][b],c);
}
floyd();
while(q--){
int a,b;
scanf("%d%d",&a,&b);
if(g[a][b]>INF/2) printf("impossible\n");
else printf("%d\n",g[a][b]);
}
return 0;
}
prim求最小生成树
#include<bits/stdc++.h>
using namespace std;
const int N=510;
const int INF=0x3f3f3f3f;
int g[N][N];
int dis[N];
bool st[N];
int n,m;
int prime(){
memset(dis,0x3f,sizeof dis);
int ans=0;
for(int i=0;i<n;i++){
int t=-1;
for(int j=1;j<=n;j++){
if(!st[j]&&(t==-1||dis[t]>dis[j])){
t=j;
}
}
if(i&&dis[t]==INF) return INF;
if(i) ans+=dis[t];
st[t]=1;
for(int j=1;j<=n;j++){
dis[j]=min(dis[j],g[t][j]);
}
}
return ans;
}
int main(){
scanf("%d%d",&n,&m);
memset(g,0x3f,sizeof g);
while(m--){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
g[a][b]=g[b][a]=min(g[a][b],c);
}
int t=prime();
if(t==INF) printf("impossible\n");
else printf("%d\n",t);
return 0;
}
Kruskal算法求最小生成树
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int p[3*N];
struct Edge{
int a,b,w;
}edge[2*N];
int n,m;
bool cmp(Edge c,Edge d){
return c.w<d.w;
}
int find(int x){
if(p[x]!=x) p[x]=find(p[x]);
return p[x];
}
int main(){
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
edge[i]={a,b,c};
}
for(int i=1;i<=n;i++) p[i]=i;
sort(edge,edge+m,cmp);
int ans=0,cnt=0;
for(int i=0;i<m;i++){
int a=edge[i].a,b=edge[i].b,w=edge[i].w;
a=find(a),b=find(b);
if(a!=b){
p[a]=b;
ans+=w;
cnt++;
}
}
if(cnt<n-1) printf("impossible\n");
else printf("%d",ans);
return 0;
}
声明:
所有模板借鉴于yxc算法基础课,仅供自己复习蓝桥使用。