模板合集

第一个堆模板

二叉堆性质优先级最大的在堆顶

插入操作是开出一个空间然后从堆底切换到一个合适的位置

删除操作就是把最下面的和最上面的换位置,再进行调整

有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]);
    }
}

 

转载于:https://www.cnblogs.com/NGUalexzhang/p/9753825.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值