NOIP2020模板

NOIP模板

并查集

int find(int x)
{
	if(f[x]==x)
	return f[x];
	else 
	return f[x]=find(f[x]);
}
void merge(int x,int y)
{
	int fx=find(x);
	int fy=find(y);
	if(fx!=fy)
	f[fx]=fy;
}

快速幂

#include<bits/stdc++.h>
using namespace std;
#define int long long
int b,p,k;
int qpow(int b,int p)
{
	int ret=1,base=b;
	while(p>0)
	{
		if(p&1)
			ret*=base;
		ret%=k;
		base*=base;
		base%=k;
		p>>=1;
	}
	return ret;
}
signed main()
{
	scanf("%lld%lld%lld",&b,&p,&k);
	printf("%lld^%lld mod %lld=",b,p,k);
	if(k==1)
	{
		cout << 0;
		return 0;
	}
	int sr=qpow(b,p);
	printf("%lld",sr);
	return 0;
}

线性筛质数

void euler(int n)
{
	for(int i=2;i<=n;i++)
	{
		if(!v[i])
		prime[++cnt]=i;
		for(int j=1;j<=cnt&&i*prime[j]<=n;j++)
		{
			v[i*prime[j]]=1;
			if(i%prime[j]==0)
			break;
		}
	}
}

SPFA

void spfa(int s)
{
	for(int i=1;i<=n;i++)
	dis[i]=2147483647;
	memset(inq,0,sizeof(inq));
	queue<int> q;
	q.push(s);
	inq[s]=1;
	dis[s]=0;
	while(!q.empty())
	{
		int x=q.front();
		q.pop();
		inq[x]=0;
		for(int i=head[x];i;i=nxt[i])
		{
			int y=to[i];
			int z=val[i];
			if(dis[y]>dis[x]+z)
			{
				dis[y]=dis[x]+z;
				if(!inq[y])
				inq[y]=1,q.push(y);
			}
		}
	}
}

注意:看好是否为双向边


DIJ

priority_queue<pair<int,int> > q;
void dij(int s)
{
	memset(dis,0x3f,sizeof(dis));
	dis[s]=0;
	q.push(make_pair(0,s));
	while(!q.empty())
	{
		int x = q.top().second;
		q.pop();
		if(v[x])
		continue;
		v[x]=1;
		for(int i=head[x];i;i=nxt[i])
		{
			int y=to[i];
			if(dis[y]>dis[x]+val[i])
			{
				dis[y]=dis[x]+val[i];
				q.push(make_pair(-dis[y],y));
			}
		}
	}
}

树状数组

namespace BIT
{
	int tr[maxn];
	void update(int x,int v)
	{
		for(int i=x;i<=n;i+=i&-i)
		tr[i]+=v;
	}
	int query(int x)
	{
		int ret=0;
		for(int i=x;i;i-=i&-i)
		ret+=tr[i];
		return ret;
	}
}

注意查询时减一


单调队列/滑动窗口

for(int i=1;i<=n;i++)
	{
		while(l<=r&&a[i]>a[q[r]])r--;
		q[++r]=i;
		while(l<=r&&i-q[l]>=k)l++;
		if(i>=k)
		printf("%d ",a[q[l]]);
	}

Tarjan缩点

void tarjan(int x)
{
	dfn[x]=low[x]=++tim;
	s.push(x);
	ins[x]=1;
	for(int i=head[x];i;i=nxt[i])
	{
		int y=to[i];
		if(!dfn[y])
		{
			tarjan(y);
			low[x]=min(low[x],low[y]);
		}
		else if(ins[y])
		low[x]=min(low[x],low[y]);
	}
	if(low[x]==dfn[x])
	{
		int cur;
		++cnt;
		do
		{
			cur=s.top();
			s.pop();
			ins[cur]=0;
			scc[cur]=cnt;
			V[cnt]+=v[cur];
		}while(cur!=x);
	}
}

注意重建图时点的问题


拓扑排序

int topo()
{
	while(!q.empty())
	{
		int x=q.front();
		q.pop();
		for(int i=head[x];i;i=nxt[i])
		{
			int y=to[i];
			dp[y]=max(dp[y],dp[x]+V[y]);
			deg[y]--;
			if(!deg[y])
			q.push(y);
		}
	}
	int ans=0;
	for(int i=1;i<=n;i++)
	ans=max(ans,dp[i]);
	return ans;
}

线性求逆元

for(int i=2;i<=n;i++)
{
	inv[i]=(ll)(p-p/i)*inv[p%i]%p;
	printf("%d
",inv[i]);
}

三分法

while(fabs(l-r)>=eps)
	{
		double mid=(l+r)/2;
		if(F(mid+eps)>F(mid-eps)) l=mid;
		else r=mid;
	}

线段树1(区间修改,区间求和)

namespace ST
{
	int tr[maxn<<2];
	int tag[maxn<<2];
	#define lson p<<1
	#define rson p<<1|1
	void mark(int l,int r,int v,int p)
	{
		tag[p]+=v;
		tr[p]+=(r-l+1)*v;
	}
	void pushdown(int l,int r,int p)
	{
		int mid=(l+r)>>1;
		mark(l,mid,tag[p],lson);
		mark(mid+1,r,tag[p],rson);
		tag[p]=0;
	}
	int query(int l,int r,int x,int y,int p)
	{
		if(x<=l&&y>=r)
		return tr[p];
		int ret=0;
		int mid=(l+r)>>1;
		if(tag[p])
		pushdown(l,r,p);
		if(x<=mid) ret+=query(l,mid,x,y,lson);
		if(y>mid) ret+=query(mid+1,r,x,y,rson);
		return ret;
	}
	void update(int l,int r,int x,int y,int v,int p)
	{
		if(x<=l&&y>=r)
		{
			mark(l,r,v,p);
			return;
		}
		int mid=(l+r)>>1;
		if(tag[p])
		pushdown(l,r,p);
		if(x<=mid) update(l,mid,x,y,v,lson);
		if(y>mid) update(mid+1,r,x,y,v,rson);
		tr[p]=tr[lson]+tr[rson];
	} 
	void build(int l,int r,int p)
	{
		if(l==r)
		{
			scanf("%lld",&tr[p]);
			return ;
		}
		int mid=(l+r)>>1;
		build(l,mid,lson);
		build(mid+1,r,rson);
		tr[p]=tr[lson]+tr[rson];
	}
}

SPFA判负环

bool spfa()
{
	q.push(1);
	inq[1]=1;
	memset(dis,0x3f,sizeof(dis));
	memset(inq,0,sizeof(inq));
	memset(cnt,0,sizeof(cnt));
	dis[1]=0;
	while(!q.empty())
	{
		int x=q.front();
		q.pop();
		inq[x]=0;
		for(int i=head[x];i;i=nxt[i])
		{
			int y=to[i];
			if(dis[y]>dis[x]+val[i])
			{
				dis[y]=dis[x]+val[i];
				cnt[y]=cnt[x]+1;
				if(cnt[y]>n+1)
				return 1;
				if(!inq[y])
				q.push(y),inq[y];
			}
		}
	}
	return 0;
}

注意初始化


单调栈

	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		while(a[s[top]]<a[i]&&top!=0)
		{
			l[s[top]]=i;
			top--;
		}
		s[++top]=i;
	}

差分约束

#include<bits/stdc++.h>
using namespace std;
int n,m;
#define maxn 600100
int head[maxn],nxt[maxn],to[maxn],val[maxn],tot=0;
void add(int x,int y,int z)
{
	to[++tot]=y;
	nxt[tot]=head[x];
	val[tot]=z;
	head[x]=tot;
}
int dis[maxn],inq[maxn],cnt[maxn];
queue<int> q;
bool spfa(int s)
{
	memset(dis,0x3f,sizeof(dis));
	memset(inq,0,sizeof(inq));
	memset(cnt,0,sizeof(cnt));
	dis[s]=0;
	cnt[s]=1;
	inq[s]=1;
	q.push(s);
	while(!q.empty())
	{
		int x=q.front();
		q.pop();
		inq[x]=0;
		for(int i=head[x];i;i=nxt[i])
		{
			int y=to[i];
			if(dis[y]>dis[x]+val[i])
			{
				dis[y]=dis[x]+val[i];
				cnt[y]=cnt[x]+1;
				if(cnt[y]>n+1)
				return 1;
				if(!inq[y])
				q.push(y),inq[y]=1;	
			}
		}
	}
	return 0;
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
	{
		int x,y,z;
		scanf("%d%d%d",&x,&y,&z);
		add(y,x,z);
	}
	for(int i=1;i<=n;i++)
	add(0,i,0);
	if(!spfa(0))
	{
		for(int i=1;i<=n;i++)
		printf("%d ",dis[i]);
	}
	else 
	printf("NO
");
	return 0;
}

注意判负环


原文地址:https://www.cnblogs.com/Marcelo/p/14082367.html