第一个堆模板
二叉堆性质优先级最大的在堆顶
插入操作是开出一个空间然后从堆底切换到一个合适的位置
删除操作就是把最下面的和最上面的换位置,再进行调整
有stl,但还是了解一下原理为好
#include <cstdio> #include <algorithm> #include <cstring> using namespace std; int heap[1000005],n; int siz; void push(int x){ heap[++siz]=x; int now=siz; while(now){ int nxt=now>>1; if(heap[nxt]>heap[now]) swap(heap[nxt],heap[now]); else break; now=nxt; } return; } void pop(){ swap(heap[siz],heap[1]);siz--; int now=1; while((now<<1)<=siz){ int nxt=now<<1; if(nxt+1<=siz&&heap[nxt+1]<heap[nxt]) nxt++; if(heap[nxt]<heap[now]) swap(heap[nxt],heap[now]); else break; now=nxt; } } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ int opt,x; scanf("%d",&opt); if(opt==1){ scanf("%d",&x); push(x); } if(opt==3){ pop(); } if(opt==2) printf("%d\n",heap[1]); } return 0; }
第二个快排
系统也为其提供了函数
知其然,知其所以然
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; int n,a[100005]; void q_sort(int l,int r){ int i=l,j=r; int mid=a[(l+r)>>1]; if(i>=j) return; while(i<=j){ while(a[j]>mid) j--; while(a[i]<mid) i++; if(i<=j){ swap(a[i],a[j]); i++,j--; } } if(l<j) q_sort(l,j); if(i<r) q_sort(i,r); } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); q_sort(1,n); for(int i=1;i<=n;i++) printf("%d ",a[i]); return 0; }
第三个ST表模板
利用的倍增法
#include <cstdio> #include <algorithm> #include <cstring> #include <cmath> using namespace std; int n,m,maxn[100005][21]; int query(int l,int r){ int k=log2(r-l+1); return max(maxn[l][k],maxn[r-(1<<k)+1][k]); } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&maxn[i][0]); for(int i=1;i<=21;i++) for(int j=1;j+(1<<i)-1<=n;j++) maxn[j][i]=max(maxn[j][i-1],maxn[j+(1<<(i-1))][i-1]); while(m--){ int l,r; scanf("%d%d",&l,&r); printf("%d\n",query(l,r)); } return 0; }
第四个lca最近公共祖先模板
也是利用了倍增法
#include <cstdio> #include <algorithm> #include <cstring> using namespace std; int n,m,s,head[500005],nxt[1200000],to[1200000],ce,dep[500005],fa[500005][22],lg[500005]; void add(int u,int v){ to[++ce]=v;nxt[ce]=head[u];head[u]=ce; } void dfs(int now,int fat){ dep[now]=dep[fat]+1; fa[now][0]=fat; for(int i=1;(1<<i)<=dep[now];i++) fa[now][i]=fa[fa[now][i-1]][i-1]; for(int i=head[now];i;i=nxt[i]) if(to[i]!=fat) dfs(to[i],now); } int lca(int x,int y){ if(dep[x]<dep[y]) swap(x,y); while(dep[x]>dep[y]) x=fa[x][lg[dep[x]-dep[y]]-1]; if(x==y) return x; for(int i=lg[dep[x]]-1;i>=0;i--) if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; return fa[x][0]; } int main(){ scanf("%d%d%d",&n,&m,&s); for(int i=1;i<n;i++){ int a,b; scanf("%d%d",&a,&b); add(a,b);add(b,a); } dfs(s,0); for(int i=1;i<=n;i++) lg[i]=lg[i-1]+((1<<lg[i-1])==i); for(int i=1;i<=m;i++){ int x,y; scanf("%d%d",&x,&y); printf("%d\n",lca(x,y)); } return 0; }
第五个树状数组
#include <cstdio> #include <algorithm> #include <cstring> using namespace std; int tree[2000005]; int n,m; int lowbit(int x){ return x&-x; } void add(int x,int y){ while(x<=n){ //printf("%d\n",x); tree[x]+=y; x+=lowbit(x); } } int query(int x){ int sum=0; while(x>0){ sum+=tree[x]; x-=lowbit(x); } return sum; } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ int x; scanf("%d",&x); add(i,x); } while(m--){ int opt; int x,y; scanf("%d%d%d",&opt,&x,&y); if(opt==1) add(x,y); else printf("%d\n",query(y)-query(x-1)); } //printf("%d",tree[2]); return 0; }
第六个模板 割顶(割点)
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; int n,m; int head[20005],nxt[200005],to[200005],ce; int dfn[20005],low[20005],siz; bool cut[20005]; void add(int u,int v){ to[++ce]=v;nxt[ce]=head[u];head[u]=ce; } void tarjan(int now,int fat){ dfn[now]=low[now]=++siz; int chi=0; for(int i=head[now];i;i=nxt[i]){ int v=to[i]; if(!dfn[v]){ tarjan(v,now); low[now]=min(low[now],low[v]); if(low[v]>=dfn[now]&&now!=fat) cut[now]=1; if(now==fat) chi++; } low[now]=min(low[now],dfn[v]); } if(chi>=2&&now==fat) cut[now]=1; } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int x,y; scanf("%d%d",&x,&y); add(x,y);add(y,x); } for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i,i); int ans=0; for(int i=1;i<=n;i++) if(cut[i]) ans++; printf("%d\n",ans); for(int i=1;i<=n;i++) if(cut[i]) printf("%d ",i); return 0; }
第七个 kmp
#include <cstdio> #include <algorithm> #include <cstring> using namespace std; char s1[1000005],s2[1000005]; int kmp[1000005]; int main(){ scanf("%s%s",s1+1,s2+1); int len1=strlen(s1+1); int len2=strlen(s2+1); int j=0; for(int i=2;i<=len2;i++){ while(s2[j+1]!=s2[i]&&j) j=kmp[j]; if(s2[j+1]==s2[i]) j++; kmp[i]=j; } j=0; for(int i=1;i<=len1;i++){ while(j&&s2[j+1]!=s1[i]) j=kmp[j]; if(s1[i]==s2[j+1]) j++; if(j==len2){ printf("%d\n",i-len2+1); j=kmp[j]; } } for(int i=1;i<=len2;i++) printf("%d ",kmp[i]); return 0; }
线性求解逆元
#include<bits/stdc++.h> #define N 3000010 typedef long long ll; using namespace std; int inv[N],n,p; inline int read(){ int f=1,x=0;char ch; do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9'); do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9'); return f*x; } int main(){ n=read();p=read();inv[1]=1;puts("1"); for(int i=2;i<=n;i++){ inv[i]=(ll)(p-p/i)*inv[p%i]%p; printf("%d\n",inv[i]); } }