[置顶] 模板库

这里贴出各种算法与数据结构的模板。这篇文章将持续更新。

杂项

struct封装的一些实用的东西

高精度模板

//留坑

神奇的优化

读入优化

int read()
{
    int t=0,p=1;
    for(ch=getchar();ch<'0' || ch>'9';ch=getchar())
        if(ch=='-') p=-1;
    for(;'0'<=ch && ch<='9';ch=getchar()) t=t*10+ch-'0';
    return t*p;
}

算法篇

求树的重心

void find(int v,int from,int tot)
{
    sum[v]=1;
    int maxi=0;
    for(int i=last[v];i;i=next[i])
    {
        int u=to[i];
        if(u==from || bz[u]) continue;
        find(u,v,tot);
        sum[v]+=sum[u];
        maxi=max(maxi,sum[u]);
    }
    int t=max(maxi,tot-sum[v]);
    if(t<=val) val=t,root=v;
}

求LCA的倍增算法

int lca(int u,int v)
{
    if(deep[u]<deep[v]) swap(u,v);
    fd(i,int(log2(deep[u])),0)
        if(deep[f[u][i]]>=deep[v]) u=f[u][i];
    fd(i,int(log2(deep[u])),0)
        if(f[u][i]!=f[v][i]) u=f[u][i],v=f[v][i];
    if(u!=v) return f[u][0];
    return u;
}

求强连通分量or双连通分量or割点or桥的Tarjan算法

void tarjan(int v)
{
    stack[++top]=v;
    low[v]=dfn[v]=++now;
    bz[v]=vis[v]=1;
    for(int i=last[v];i;i=next[i])
    {
        int u=to[i];
        if(dfn[u]==0)
        {
            tarjan(u);
            low[v]=min(low[v],low[u]);
        }
        else
        if(vis[u] && dfn[u]<low[v]) low[v]=dfn[u];
    }
    if(low[v]==dfn[v])
    {
        long long t=0;
        do
        {
            vis[stack[top--]]=0;
            t++;
        }
        while(stack[top+1]!=v);
        ans+=t*(t-1)/2;
    }
}

GAP

int aug(int v,int flow)
{
    if(v==T) return flow;
    int minh=n+1;
    for(int i=last[v];i!=0;i=next[i])
    {
        int u=to[i];
        if(c[v][u]>0)
        {
            if(h[v]==h[u]+1)
            {
                int f=aug(u,min(flow,c[v][u]));
                if(f>0)
                {
                    c[v][u]-=f;
                    c[u][v]+=f;
                    return f;
                }
                if(h[S]>n) return 0;
            }
            minh=min(minh,h[u]+1);
        }
    }
    if(--vh[h[v]]==0) h[S]=n+1;
    h[v]=minh;
    vh[h[v]]++;
    return 0;
}

数论

extended欧几里得算法

void gcd(ll a,ll b,ll &x,ll &y)
{
     if(b==0)
     {
         x=1,y=0;
         return;
     }
     ll xx,yy;
     gcd(b,a%b,xx,yy);
     x=yy,y=xx-a/b*yy;
}

欧拉函数 φ 的计算

ll phi(int n)
{
    ll t=n;
    for(int i=2;i*i<=n;i++)
        if(!(n%i))
        {
            t=t/i*(i-1);
            while(!(n%i)) n/=i;
        }
    if(n>1) t=t/n*(n-1);
    return num;
}

高斯消元

fo(i,1,n)
{
    fo(j,i+1,n) a[i][j]/=a[i][i];
    b[i]/=a[i][i];
    a[i][i]=1;
    fo(j,i+1,n)
    {
        fo(k,i+1,n) a[j][k]-=a[j][i]*a[i][k];
        b[j]-=a[j][i]*b[i];
        a[j][i]=0;
    }
}
fd(i,n,1)
{
    fo(j,1,i-1)
    {
        b[j]-=a[j][i]*b[i];
        a[j][i]=0;
    }
}
fo(i,1,n) printf("%.2lf ",b[i]);

线性筛法

void pre(int n)
{

    mu[1]=1;
    fo(i,2,n)
    {
        if(!bz[i])
        {
            mu[i]=-1;
            pri[++pri[0]]=i;
        }
        fo(j,1,pri[0])
        {
            int t=i*pri[j];
            if(t>n) break;
            bz[t]=1;
            if(i%pri[j]==0)
            {
                mu[t]=0;
                break;
            }
            mu[t]=-mu[i];
        }
    }
}

自然数幂和(第一类斯特林数)

ll Sk(ll n)
{
    f[0]=n;
    fo(i,1,k)
    {
        f[i]=1;
        fo(j,n-i+1,n+1)
            if(j%(i+1)) f[i]=qmul(f[i],j);
            else f[i]=qmul(f[i],j/(i+1));
        fo(j,0,i-1)
            (f[i]=f[i]-qmul(ss[i][j],f[j])+mo)%mo;
    }
    return f[k];
}

ss 表示带符号第一类斯特林数。其递推公式如下:

ss[0][0]=1;
fo(i,1,k)
 fo(j,1,i) ss[i][j]=(ss[i-1][j-1]-(i-1)*ss[i-1][j]%mo+mo)%mo;

字符串

KMP

void get(char *s)
{
    int len=strlen(s+1),j=0;
    fo(i,2,len)
    {
        while(j && s[i]!=s[j+1]) j=f[j];
        f[i]=s[i]==s[j+1]?(++j):(j=0);
    }
}
int KMP(char *s1,char *s2)
{
    get(s2);
    int j=0,ans=0,len1=strlen(s1+1),len2=strlen(s2+1);
    fo(i,1,len1)
    {
        while(j && s1[i]!=s2[j+1]) j=f[j];
        if(s1[i]==s2[j+1]) j++;
        if(j==len2) ans++;
    }
    return ans;
}

SA的倍增构造

void DA()
{
    int mx=0;
    fo(i,1,n) mx=max(mx,wv[i]=x[i]=s[i]-'a'+1);
    fill(ws,ws+mx+1,0);
    fo(i,1,n) ws[wv[i]]++;
    fo(i,1,mx) ws[i]+=ws[i-1];
    fd(i,n,1) SA[ws[wv[i]]--]=i;
    for(int len=1;len<=n;len*=2)
    {
        int m=0;
        fo(i,n-len+1,n) y[++m]=i;
        fo(i,1,n)
            if(SA[i]>len) y[++m]=SA[i]-len;
        mx=0;
        fo(i,1,n) mx=max(mx,wv[i]=x[y[i]]);
        fill(ws,ws+mx+1,0);
        fo(i,1,n) ws[wv[i]]++;
        fo(i,1,mx) ws[i]+=ws[i-1];
        fd(i,n,1) SA[ws[wv[i]]--]=y[i];
        fo(i,1,n) y[i]=x[i],x[i]=0;
        x[SA[m=1]]=1;
        fo(i,2,n) x[SA[i]]=cmp(SA[i-1],SA[i],len)?m:++m;
        if(m==n) break;
    }
    fo(i,1,n) rank[SA[i]]=i;
}

Manacher算法

int maxi=0,mid,ans=0;
for(int i=1;i<=len;i++)
{
    f[i]=1; 
    if(maxi>i) f[i]=min(f[2*mid-i],maxi-i);
    while(s2[i+f[i]]==s2[i-f[i]]) f[i]++;
    if(f[i]+i>maxi)
    {
        maxi=f[i]+i;
        mid=i;
    }
    ans=max(ans,f[i]-1);
}

你可能感兴趣的:(数据结构,算法,模板库)