模板合集(1)

文章目录

  • 基础
    • 对拍程序
    • 快速幂
    • 读入优化
    • 二分
    • 线性筛
  • 图论
    • 邻接表
    • LCA
    • SPFA
    • 二分图匹配
    • 网络流
  • 数据结构
    • 并查集
    • 线段树(区间加/乘,求和模板)
    • 树状数组
  • 字符串
    • KMP算法

基础

对拍程序

转自http://blog.csdn.net/wlx65003/article/details/51149196

@echo off  
:loop  
    rand.exe > in.txt
    my.exe < in.txt > myout.txt
    std.exe < in.txt > stdout.txt
    fc myout.txt stdout.txt
if not errorlevel 1 goto loop  
pause
goto loop

快速幂

#include
#include
#include
using namespace std;
typedef long long ll;
ll x,y,m;
ll qsm(ll x,ll y,ll m)
{
	ll ret=1;
	x%=m;
	while (y)
	{
		if (y&1) ret*=x;
		ret%=m,x*=x,x%=m,y/=2;
	}
	return ret;
}
int main()
{
	scanf("%lld%lld%lld",&x,&y,&m),printf("%lld",qsm(x,y,m));
}

读入优化

必备技巧

inline void read(int &x)
{
	x=0;
	int f=1;
	char ch=getchar();
	while (!isdigit(ch)) 
	{
		if (ch=='-') f=-1;
		ch=getchar();
	}
	while (isdigit(ch))
	{
		x=(x<<3)+(x<<1)+ch-'0';
		ch=getchar();
	}
	x*=f;
}

二分

推荐两个函数:lower_bound&upper_bound(具体用法不再解释)
对于线性递增的数组,x值的位置下界为lower_bound(a+1,a+n+1,x)-a,上界为upper_bound(a+1,a+n+1,x)-a-1;
求下界:

void binary_find()
{
	l=1,r=INF;
	while (l!=r)
	{
		int mid=(l+r)/2;
		if (check(mid)) r=mid;else l=mid+1;
	}
}

求上界:(注意细节)

void binary_find()
{
	l=1,r=INF;
	while (l!=r)
	{
		int mid=(l+r+1)/2;
		if (check(mid)) l=mid;else r=mid-1;
	}
}

线性筛

时间复杂度仅为O(n)。
筛质数:

#include
#include
#include
#define maxn 10000050
using namespace std;
int f[maxn],p[maxn],top=0,i,j,n;
int main()
{
	scanf("%d",&n),f[0]=f[1]=1,p[0]=0;
	for (i=2;i<=n;i++)
	{
		if (f[i]==0) p[++top]=i;
		for (j=1;j<=top&&i*p[j]<=n;j++)
		{
			f[i*p[j]]=1;
			if (i%p[j]==0) break;
		}
	}
	printf("%d\n",top);
	for (i=1;i<=top;i++) printf("%d ",p[i]);
}

ϕ \phi ϕ:

#include
#define N 1000050
using namespace std;
int prime[N],p[N],n,tot=0,phi[N];
int main()
{
	scanf("%d",&n),phi[1]=1;
	for (int i=2;i<n;i++)
	{
		if (!p[i]) prime[++tot]=i,phi[i]=i-1;
		for (int j=1;j<=tot&&i*prime[j]<n;j++) 
		{
			p[i*prime[j]]=1;
			if (i%prime[j]==0) {phi[i*prime[j]]=phi[i]*prime[j];break;}
			phi[i*prime[j]]=phi[i]*(prime[j]-1);
		}
	}
	for (int i=1;i<=tot;i++) printf("%d\n",prime[i]);
	for (int i=1;i<=n;i++) printf("%d\n",phi[i]);
}

μ \mu μ:

#include
#define N 1000050
using namespace std;
int prime[N],p[N],n,tot=0,mu[N];
int main()
{
	scanf("%d",&n),mu[1]=1;
	for (int i=2;i<n;i++)
	{
		if (!p[i]) prime[++tot]=i,mu[i]=-1;
		for (int j=1;j<=tot&&i*prime[j]<n;j++) 
		{
			p[i*prime[j]]=1;
			if (i%prime[j]==0) {mu[i*prime[j]]=0;break;}
			mu[i*prime[j]]=-mu[i];
		}
	}
	for (int i=1;i<=tot;i++) printf("%d\n",prime[i]);
	for (int i=1;i<=n;i++) printf("%d\n",mu[i]);
}

图论

邻接表

有很多种写法,强烈安利我的这种写法,操作简单、便捷。

#include
#include
#include
#define maxn 100050
#define add(u,v,vv) to[++top]=head[u],head[u]=top,w[top]=v,val[top]=vv
#define For(x) for(int h=head[x],o=w[h],v=val[h];h;o=w[h=to[h]],v=val[h])
using namespace std;
int n,m,i,top=0,head[maxn*2],to[maxn*2],w[maxn*2],val[maxn*2],u,v,vv;
int main()
{
	scanf("%d%d",&n,&m);
	for (i=1;i<=m;i++) scanf("%d%d%d",&u,&v,&vv),add(u,v,vv);
	for (i=1;i<=n;i++) For(i) printf("%d to %d:%d\n",i,o,v);
}

LCA

#include
#include
#include
#define maxn 100050
#define add(u,v) to[++top]=head[u],head[u]=top,w[top]=v
#define For(x) for(int h=head[x],o=w[h];h;o=w[h=to[h]])
using namespace std;
int n,q,u,v,i,top=0,f[maxn][25],d[maxn],head[maxn*2],to[maxn*2],w[maxn*2];
inline void dfs(int x,int fa)
{
	d[x]=d[fa]+1;
	for (i=1;i<=20;i++) f[x][i]=f[f[x][i-1]][i-1];
	For(x) if (o!=fa) f[o][0]=x,dfs(o,x);
}
inline int lca(int u,int v)
{
	if (d[u]<d[v]) swap(u,v);
	for (int i=20;i>=0;i--) 
	{
		if (d[f[u][i]]>=d[v]) u=f[u][i];
		if (u==v) return u;
	}
	for (int i=20;i>=0;i--) if (f[u][i]!=f[v][i]) u=f[u][i],v=f[v][i];
	return f[u][0];
}
int main()
{
	scanf("%d%d",&n,&q);
	for (i=1;i<n;i++) scanf("%d%d",&u,&v),add(u,v),add(v,u);
	dfs(1,0);
	while (q--) scanf("%d%d",&u,&v),printf("%d",lca(u,v));
}

SPFA

队列优化的bfs,时间复杂度O(km)(k约等于2)。

#include
#include
#include
#define maxn 100050
#define add(u,v,vv) to[++top]=head[u],head[u]=top,w[top]=v,val[top]=vv
#define For(x) for(int h=head[x],o=w[h],v=val[h];h;o=w[h=to[h]],v=val[h])
using namespace std;
int top=0,l,r,q[maxn*2],dis[maxn],bo[maxn],head[maxn],to[maxn],w[maxn],val[maxn],n,m,u,v,vv,s,t,x;
inline void spfa()
{
	q[l=r=0]=s,memset(bo,0,sizeof(bo)),memset(dis,0x7f,sizeof(dis)),dis[s]=0,bo[s]=1;
	while (l<=r)
	{
		x=q[l];
		For(x) if (dis[x]+v<dis[o])
		{
			dis[o]=dis[x]+v;
			if (!bo[o]) bo[o]=1,q[++r]=o;
		}
		l++,bo[x]=0;
	}
}
int main()
{
	scanf("%d%d",&n,&m);
	while (m--) scanf("%d%d%d",&u,&v,&vv),add(u,v,vv);
	scanf("%d%d",&s,&t),spfa(),printf("%d",dis[t]);
}


二分图匹配

#include
#include
#include
#define add(u,v) to[++top]=head[u],head[u]=top,w[top]=v
#define For(x) for(int h=head[x],o=w[h];h;o=w[h=to[h]])
#define maxn 5050
using namespace std;
int top=0,to[maxn*maxn],head[maxn*maxn],w[maxn*maxn],t[maxn],vis[maxn],ans=0,n,m,e,u,v;
inline bool dfs(int x)
{
	For(x) if (!vis[o]) 
	{
		vis[o]=1;
		if (!t[o]||dfs(o)) {t[o]=x; return 1;}
	}
	return 0;
}
int main()
{
	scanf("%d%d%d",&n,&m,&e);
	while (e--) 
	{
		scanf("%d%d",&u,&v);
		if (u<=n&&v<=m) add(u,v);
	}
	for (int i=1;i<=n;i++)
	{
		memset(vis,0,sizeof(vis));
		if (dfs(i)) ans++;
	}
	printf("%d",ans);
} 

网络流

#include
#include
#include
#define maxn 10050
#define maxm 100050
#define INF 1000000000
#define add(u,v,vv) to[++top]=head[u],head[u]=top,w[top]=v,cap[top]=vv
#define For(x) for(int h=head[x],o=w[h];h;o=w[h=to[h]])
using namespace std;
int top=1,to[maxm*2],head[maxm*2],w[maxm*2],cap[maxm*2],level[maxn],q[maxn*8],l,r,s,t,x;
int n,m,u,v,vv;
inline bool bfs()
{
	memset(level,0,sizeof(level));
	q[l=r=0]=s,level[s]=1;
	while (l<=r)
	{
		x=q[l++];
		For(x) if (cap[h]&&level[o]==0) level[o]=level[x]+1,q[++r]=o;
	}
	return level[t];
}
inline int dfs(int x,int maxflow)
{
	if (x==t||!maxflow) return maxflow;
	int ret=0;
	For(x) if (cap[h]&&level[o]==level[x]+1) 
	{
		int tmp=dfs(o,min(cap[h],maxflow));
		ret+=tmp,maxflow-=tmp,cap[h]-=tmp,cap[h^1]+=tmp; 
	}
	if (!ret) level[x]=0;
	return ret;
}
inline int dinic()
{
	int ret=0;
	while (bfs()) 
		ret+=dfs(s,INF);
	return ret;
}
int main()
{
	scanf("%d%d%d%d",&n,&m,&s,&t);
	for (int i=1;i<=m;i++) scanf("%d%d%d",&u,&v,&vv),add(u,v,vv),add(v,u,0);
	printf("%d",dinic());
} 

数据结构

并查集

不带权的版本

#include
#include
#include
#define maxn 10050
using namespace std;
int f[maxn],n,m,u,v,opt;
inline int find(int x)
{
	if (x==f[x]) return x;
	f[x]=find(f[x]); return f[x];
}
inline void union_(int u,int v) {f[find(u)]=find(v);}
int main()
{
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;i++) f[i]=i;
	while (m--)
	{
		scanf("%d%d%d",&opt,&u,&v);
		if (opt==1) union_(u,v);
		else if (find(u)==find(v)) printf("Y\n");else printf("N\n");
	}
}

线段树(区间加/乘,求和模板)

难度:4

#include
#include
#include
#include
#define maxn 100050
using namespace std;
typedef long long ll;
int a[maxn],ql,qr,val,opt,n,m,p;
struct segment_tree
{
	ll t[maxn*4],lz1[maxn*4],lz2[maxn*4];
	inline void pushup(int x) {t[x]=t[x*2]+t[x*2+1];}
	inline void pushdown(int x,int l,int r)
	{
		if (lz1[x]==1&&lz2[x]==0) return;
		if (lz1[x]!=1)
		{
			lz1[x*2]=(lz1[x]*lz1[x*2])%p;
			lz1[x*2+1]=(lz1[x]*lz1[x*2+1])%p;
			lz2[x*2]=(lz1[x]*lz2[x*2])%p;
			lz2[x*2+1]=(lz1[x]*lz2[x*2+1])%p;
			t[x*2]=(t[x*2]*lz1[x])%p;
			t[x*2+1]=(t[x*2+1]*lz1[x])%p;
			lz1[x]=1;
		}
		int mid=(l+r)/2;
		if (lz2[x]!=0)
		{
			lz2[x*2]=(lz2[x*2]+lz2[x])%p;
			lz2[x*2+1]=(lz2[x*2+1]+lz2[x])%p;
			t[x*2]=(t[x*2]+(mid-l+1)*lz2[x])%p;
			t[x*2+1]=(t[x*2+1]+(r-mid)*lz2[x])%p;
			lz2[x]=0;
		}
	}
	inline void build(int x,int l,int r)
	{
		if (l==r) {t[x]=a[l],lz1[x]=1;return;}
		int mid=(l+r)/2;
		build(x*2,l,mid),build(x*2+1,mid+1,r),pushup(x),lz1[x]=1;
	}
	inline void upd(int x,int l,int r,int ql,int qr,int val,int k) //k=1:*  k=2:+ 
	{
		if (l==ql&&r==qr)
		{
			if (k==1) lz1[x]=(lz1[x]*val)%p,lz2[x]=(lz2[x]*val)%p,t[x]=(t[x]*val)%p;
			if (k==2) lz2[x]=lz2[x]+val,t[x]=(t[x]+val*(r-l+1))%p;
			return;
		}
		pushdown(x,l,r);
		int mid=(l+r)/2;
		if (qr<=mid) upd(x*2,l,mid,ql,qr,val,k);
		else if (ql>mid) upd(x*2+1,mid+1,r,ql,qr,val,k);
		else upd(x*2,l,mid,ql,mid,val,k),upd(x*2+1,mid+1,r,mid+1,qr,val,k);
		pushup(x);
	}
	inline ll query(int x,int l,int r,int ql,int qr)
	{
		if (l==ql&&r==qr) {return t[x]%p;}
		pushdown(x,l,r),pushup(x);
		int mid=(l+r)/2;
		if (qr<=mid) return query(x*2,l,mid,ql,qr)%p;
		else if (ql>mid) return query(x*2+1,mid+1,r,ql,qr)%p;
		else return (query(x*2,l,mid,ql,mid)+query(x*2+1,mid+1,r,mid+1,qr))%p;
	}
}s;
inline void rd(int &x)
{
	x=0;
	char ch=getchar();
	while (!isdigit(ch)) ch=getchar();
	while (isdigit(ch)) x=(x<<3)+(x<<1)+ch-48,ch=getchar();
}
int main()
{
	rd(n),rd(m),rd(p);
	for (int i=1;i<=n;i++) rd(a[i]);
	s.build(1,1,n);
	while (m--)
	{
		rd(opt);
		if (opt==1) rd(ql),rd(qr),rd(val),s.upd(1,1,n,ql,qr,val,1);
		if (opt==2) rd(ql),rd(qr),rd(val),s.upd(1,1,n,ql,qr,val,2);
		if (opt==3) rd(ql),rd(qr),printf("%lld\n",s.query(1,1,n,ql,qr));
	}
}


树状数组

单点加/区间求和:(l到r和为query®-query(l-1))
区间加/单点询问:(l到r加x:add(l,x),add(r+1,-x))

inline void add(int x,int y) {while (x<=n) t[x]+=y,x+=lowbit(x);}
inline int query(int x)
{
	int ret=0;
	while (x>=1) ret+=t[x],x-=lowbit(x);
	return ret;
}

区间修改+查询:

inline void add(ll p,ll x){
    for(int i=p;i<=n;i+=lowbit(i))
        sum1[i]+=x,sum2[i]+=x*p;
}
inline void Add(ll l,ll r,ll x){add(l,x),add(r+1,-x);}
inline ll ask(ll p){
    ll res=0;
    for (int i=p;i;i-=lowbit(i)) res+=(p+1)*sum1[i]-sum2[i];
    return res;
}
inline ll Ask(ll l, ll r){return ask(r)-ask(l-1);}

字符串


KMP算法

#include
#define N 2000050
using namespace std;
char s[N],t[N];
int next[N],len1,len2,k;
int main()
{
    scanf("%s",s+1),scanf("%s",t+1),k=0,len1=strlen(s+1),len2=strlen(t+1),next[1]=0;
    for (int i=2;i<=len2;i++)
    {
        while (k>0&&t[i]!=t[k+1]) k=next[k];
        if (t[i]==t[k+1]) k++;
        next[i]=k;
    } 
    k=0;
    for (int i=1;i<=len1;i++)
    {
        while (k>0&&s[i]!=t[k+1]) k=next[k];
        if (s[i]==t[k+1]) k++;
        if (k==len2) k=next[k],printf("%d\n",i-len2+1);
    }
    for (int i=1;i<=len2;i++) printf("%d ",next[i]);
}

你可能感兴趣的:(总结,总结)