临近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:可能还有很多其他模板,这里就不再多放了,要学会整理属于自己的模板,才能在需要用到它时得心应手。