一些小模板总结

临近noip了,在此整理一下一些小模板,算是自己的复习,也给一些萌新一点福利。
~\ (≧▽≦) /~

—————————————————灵梦镇楼——————————————————-

这里写图片描述

————————————————–灵梦镇楼—————————————————————

最小生成树(kruskal):
int kruskal()
{
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        fa[i]=i;
    }
    sort(tree+1,tree+m+1,cmp);
    for(int i=1;i<=m;i++)
    {
        if(find(tree[i].from)!=find(tree[i].to))
        {
            fa[find(tree[i].from)]=find(tree[i].to);
            ans+=tree[i].cost;
        }
    }
    return ans;
}
最短路(spfa):
void spfa(int s)
{
    q.push(s);
    vis[s]=1;
    dis[s]=0;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        vis[u]=0;
        for(int i=first[u];i;i=next[i])
        {
            int v=es[i].to;
            if(dis[v]>dis[u]+es[i].cost)
            {
                dis[v]=dis[u]+es[i].cost;
                if(!vis[v])
                {
                    q.push(v);
                    vis[v]=1;
                }
            }
        } 
    }
}
筛素数(埃氏筛法):
bool isprime()
{ 
    memset(prime,1,sizeof(prime));
    prime[0]=prime[1]=0;
    for(int i=2;i<=n;i++)
    {
        if(prime[i])
        {
            for(int j=i*i;j<=n;j+=i)
            {
                prime[j]=0; 
            }
        }
    }
}
倍增lca:
int dfs(int x)
{
    vis[x]=1;
    for(int i=1;i<=20;i++)
    {
        if(deep[x]>=(1<<i))
        {
            fa[x][i]=fa[fa[x][i-1]][i-1];
            dis[x][i]=dis[fa[x][i-1]][i-1]+dis[x][i-1];
        }
    }
    for(int i=first[x];i;i=next[i])
    {
        if(!vis[es[i].to])
        {
            fa[es[i].to][0]=x;
            dis[es[i].to][0]=es[i].cost;
            deep[es[i].to]=deep[x]+1;
            dfs(es[i].to);
        }
    }
}
int lca(int x,int y)
{
    if(deep[x]<deep[y])
    {
        swap(x,y);
    }
    int t=deep[x]-deep[y];
    for(int i=0;i<=20;i++)
    {
        if((t&(1<<i))!=0)
        {
            x=fa[x][i];
        }
        if(x==y)
        {
            return x;
        }
    }
    for(int i=20;i>=0;i--)
    {
        if(fa[x][i]!=fa[y][i])
        {
            x=fa[x][i],y=fa[y][i];
        }
    }
    return fa[x][0];
}
int ask(int x,int f)
{
    int s=0;
    int t=deep[x]-deep[f];
    for(int i=0;i<=20;i++)
    {
        if((t&(1<<i))!=0)
        {
            s+=dis[x][i];
            x=fa[x][i];
        }
    }
    return s;
}
Tarjan算法求强连通分量:
int dfs(int u)
{
    int lowu=pre[u]=++cnt;
    s.push(u);
    for(int i=first[u];i;i=next[i])
    {
        int v=es[i].to;
        if(!pre[v])
        {
            int lowv=dfs(v);
            lowu=min(lowu,lowv);
        }
        else if(!scc_num[v])
        {
            lowu=min(lowu,pre[v]);
        }
    }
    if(lowu==pre[u])
    {
        scc_cnt++;
        while(!s.empty())
        {
            int v=s.top();
            s.pop();
            scc_num[v]=scc_cnt;
            if(v==u)
            {
                break;
            }
        }
    }
    return lowu;
}
拓扑排序:
void TopoSort()
{
    for(int i=1;i<=n;i++)
    {
        if(!ru[i]&&!vis[i])
        {
            printf("%d ",a[i]);
            vis[i]=1;
            for(int j=first[i];j;j=next[j])
            {
                int u=es[j].to;
                if(!vis[u])
                {
                    ru[u]--;
                    if(!ru[u])
                    {
                        TopoSort();
                    }
                }
            }
        }
    }
}
线段树:
#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=400000;
struct cc{
    long long l,r,add,sum;
}tree[maxn];
long long yy[maxn];
void update(long long p)
{
    tree[p].sum=tree[p*2].sum+tree[p*2+1].sum;
    return;
}
void spread(long long p)
{
    if(!tree[p].add) return;
    tree[p*2].add+=tree[p].add;
    tree[p*2].sum+=(tree[p*2].r-tree[p*2].l+1)*tree[p].add;
    tree[p*2+1].add+=tree[p].add;
    tree[p*2+1].sum+=(tree[p*2+1].r-tree[p*2+1].l+1)*tree[p].add;
    tree[p].add=0;
    update(p);
    return;
}
void build(long long l,long long r,long long p)
{
    tree[p].l=l,tree[p].r=r;
    if(l==r)
    {
        tree[p].sum=yy[l];
        return;
    }
    spread(p);
    long long mid=(tree[p].l+tree[p].r)/2;
    build(l,mid,p*2);
    build(mid+1,r,p*2+1);
    update(p);
    return;
}
void change(long long l,long long r,long long p,long long v)
{
    if(tree[p].l>=l&&tree[p].r<=r)
    {
        tree[p].add+=v;
        tree[p].sum+=(tree[p].r-tree[p].l+1)*v;
        return;
    }
    spread(p);
    long long mid=(tree[p].l+tree[p].r)/2;
    if(l<=mid)
    {
        change(l,r,p*2,v);
    }
    if(mid+1<=r)
    {
        change(l,r,p*2+1,v);
    }
    update(p);
    return;
}
long long ask(long long l,long long r,long long p)
{
    long long ans=0;
    if(l<=tree[p].l&&tree[p].r<=r)
    {
        return tree[p].sum;
    }
    spread(p);
    long long mid=(tree[p].l+tree[p].r)/2;
    if(l<=mid)
    {
        ans+=ask(l,r,p*2);
    }
    if(mid+1<=r)
    {
        ans+=ask(l,r,p*2+1);
    }
    update(p);
    return ans;
}
int main()
{
    long long n,m;
    scanf("%lld%lld",&n,&m);
    for(long long i=1;i<=n;i++)
    {
        scanf("%lld",&yy[i]);
    }
    build(1,n,1);
    for(long long i=1;i<=m;i++)
    {
        long long s;
        scanf("%lld",&s);
        if(s==1)
        {
            long long x,y,z;
            scanf("%lld%lld%lld",&x,&y,&z);
            change(x,y,1,z);
        }
        if(s==2)
        {
            long long x,y;
            scanf("%lld%lld",&x,&y);
            printf("%lld\n",ask(x,y,1));
        }
    }
    return 0;
}
树状数组:
#include<iostream>
#include<cstdio>
using namespace std;
int lowbit(int x)
{
    return (x&(-x));
}
int a[1000000];
int n,m;
void build(int i,int x)
{
    while(i<=n)
    {
        a[i]+=x;
        i+=lowbit(i);
    }
}
int sum(int x)
{
    int ans=0;
    while(x>0)
    {
        ans+=a[x];
        x-=lowbit(x);
    }
    return ans;
}
int main()
{

    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        int x;
        scanf("%d",&x);
        build(i,x);
    }
    for(int i=1;i<=m;i++)
    {
        int s;
        scanf("%d",&s);
        if(s==1)
        {
            int x,k;
           scanf("%d%d",&x,&k);
            build(x,k);
        }
        else
        {
            int x,y;
            scanf("%d%d",&x,&y);
            printf("%d\n",sum(y)-sum(x-1));
        }
    }
    return 0;
}
扩展欧几里德:
#include<iostream>
#include<cstdio>
using namespace std;
long long a,b,x,y;
void exgcd(long long a,long long b,long long &x,long long &y)
{
    if(b==0)
    {
        x=1,y=0;
        return;
    }
    exgcd(b,a%b,x,y);
    int t=x;
    x=y,y=t-a/b*y;

}
int main()
{

    scanf("%lld%lld",&a,&b);
    exgcd(a,b,x,y);
    printf("%lld",(x+b)%b);
    return 0;
}
区间最值:
#include<iostream>
#include<cstdio>
using namespace std;
int yy[500000];
struct cc{
    int l,r,x;
}tree[500000];
void update(int p)
{
    tree[p].x=min(tree[p*2].x,tree[p*2+1].x);
    return;
}
void build(int l,int r,int p)
{
    tree[p].l=l;
    tree[p].r=r;
    if(l==r)
    {
        tree[p].x=yy[l];
        return;
    }
    int mid=(tree[p].l+tree[p].r)/2;
    build(l,mid,p*2);   
    build(mid+1,r,p*2+1);   
    update(p);
    return;
}
int ans;
void ask(int l,int r,int a,int b,int p)
{
    if(l>=a&&r<=b)
    {
        ans=min(ans,tree[p].x);
        return;
    }
    int mid=(l+r)/2;
    if(mid>=a)
    {
        ask(l,mid,a,b,p*2);
    }
    if(mid+1<=b)
    {
        ask(mid+1,r,a,b,p*2+1);
    }
    return;
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
    scanf("%d",&yy[i]); 
    }
    build(1,n,1);
    for(int i=1;i<=m;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        ans=214748364;
        ask(1,n,x,y,1);
        printf("%d ",ans);
    }
    return 0;
}

—————————————————我是华丽的分割线——————————————————-

归并排序求逆序对:
#include<iostream>
#include<cstdio>
using namespace std;
int num[40005];
int temp[40005]; 
int ans=0;
void ask(int l,int r)
{
    if(l==r)
    {
        return;
    }
    int mid=(l+r)/2;
    ask(l,mid),ask(mid+1,r);
    int p=l,pl=l,pr=mid+1;
    while(pl<=mid||pr<=r)
    {
        if(pr>r||(pl<=mid&&num[pl]<=num[pr]))
        {
            temp[p]=num[pl];    
            p++,pl++;
        }
        else
        {
            ans+=mid-pl+1;
            temp[p]=num[pr];
            p++,pr++;
        }
    }
    for(int i=l;i<=r;i++)
    {
        num[i]=temp[i];
    }
    return;
}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&num[i]);
    }
    ask(1,n);
    printf("%d",ans);
    return 0;
}
floyod(汗~):
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int dp[105][105];
int main()
{
    memset(dp,63,sizeof(dp));
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            scanf("%d",&dp[i][j]);
            dp[j][i]=dp[i][j];
        }
    }
 for(int k=1;k<=n;k++)
 {
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(k!=i&&i!=j&&j!=k)
            {
                dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]);   
            }   
        }
    }
 }
 int m;
 scanf("%d",&m);
 for(int i=1;i<=m;i++)
 {
    int x,y;
    scanf("%d%d",&x,&y);
    printf("%d\n",dp[x][y]);
 }
 return 0;
}
快速幂:
#include<iostream>
#include<cstdio>
using namespace std;
long long ksm(long long a,long long b,long long c)
{
    if(b==0)
    {
        return 1;
    }
    long long ans=ksm(a,b/2,c);
    ans=((ans%c)*(ans%c))%c;
    if(b%2==1)
    {
        ans=((ans%c)*(a%c))%c;
    }
    return ans;
}
int main()
{
    long long a,b,c;
    scanf("%lld%lld%lld",&a,&b,&c);
    printf("%lld",ksm(a,b,c));
    return 0;
}
高精度:额,随便吧,noip不好说,有兴趣的去翻翻我的博客吧。
KMP :
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int fail[1000000+10];
char s1[1000000+10];
char s2[1000000+10];
void del(int m)
{
    fail[1]=0;
    for(int i=2;i<=m;i++)
    {
        int p=fail[i-1];
        while(p&&s2[i]!=s2[p+1])
        {
            p=fail[p];
        }
        if(s2[i]==s2[p+1])
        {
            p++;
        }
        fail[i]=p;
    }
}
void solve(int n,int m)
{
    int p=0;
    for(int i=1;i<=n;i++)
    {
        while(p&&s1[i]!=s2[p+1])
        {
            p=fail[p];
        }
        if(s1[i]==s2[p+1])
        {
            p++;
        }
        if(p==m)
        {
            printf("%d\n",i-p+1);
            p=fail[p];
        }

    }
}
int main()
{
    scanf("%s",s1+1);
    scanf("%s",s2+1);
    int n=strlen(s1+1);
    int m=strlen(s2+1);
    del(m);
    solve(n,m);
    for(int i=1;i<=m;i++)
    {
        printf("%d ",fail[i]);
    }
    return 0;
}
矩阵斐波那契:
#include<iostream>
#include<cstdio>
using namespace std;
const int mod=10000;
struct matrix{
    int m[2][2];
}base,ans;
matrix multi(matrix a,matrix b)
{
    matrix tmp;
    for(int i=0;i<2;i++)
    {
        for(int j=0;j<2;j++)
        {
            tmp.m[i][j]=0;
            for(int k=0;k<2;k++)
            {
                tmp.m[i][j]=(tmp.m[i][j]+a.m[i][k]*b.m[k][j])%mod;
            }
        }
    }
    return tmp;
}
int ksm(int n)
{
    base.m[0][0]=base.m[1][0]=base.m[0][1]=1,base.m[1][1]=0;
    ans.m[0][0]=ans.m[1][1]=1,ans.m[0][1]=ans.m[1][0]=0;
    while(n)
    {
        if(n%2==1)
        {
            ans=multi(ans,base);
        }
        base=multi(base,base);
        n/=2;
    }
    return ans.m[0][1];
}
int main()
{
    int n;
    scanf("%d",&n);
    printf("%d",ksm(n));
    return 0;
}
差分:
#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=25000;
int n,m;
int num[maxn];
int pre[maxn];
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&num[i]);
    }
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        pre[x]+=z;
        pre[y+1]-=z;
    }
    for(int i=1;i<=n;i++)
    {
        pre[i]+=pre[i-1];
        num[i]+=pre[i];
    }
    for(int i=1;i<=n;i++)
    {
        printf("%d ",num[i]);
    }
    return 0;
}

ps:可能还有很多其他模板,这里就不再多放了,要学会整理属于自己的模板,才能在需要用到它时得心应手。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值