suxxsfe

一言(ヒトコト)

省选模板

  • 各种平衡树

  • (可并)堆

  • 各种莫队

  • 各种可持久化

  • 线段树合并、分裂、分治

  • LCT

  • tarjan 缩强连通分量

Graph G;
int dfn[N],low[N],dfscnt;
int stack[N],top;
int scc[N],scccnt;
void tarjan(int u){
	dfn[u]=low[u]=++dfscnt;stack[top++]=u;
	for(int v,i=G.fir[u];i;i=G.nex[i]){
		v=G.to[i];
		if(!dfn[v]){
			tarjan(v);
			low[u]=std::min(low[u],low[v]);
		}
		else if(!scc[v]) low[u]=std::min(low[u],dfn[v]);
	}
	if(dfn[u]==low[u]){
		scccnt++;
		do{
			scc[stack[--top]]=scccnt;
		}while(stack[top]^u);
	}
}
  • tarjan 求割点
Graph G;
int dfn[N],low[N],dfscnt;
int cut[N];
void tarjan(int u,int root){
	dfn[u]=low[u]=++dfscnt;
	int cnt=0;
	for(int v,i=G.fir[u];i;i=G.nex[i]){
		v=G.to[i];
		if(!dfn[v]){
			tarjan(v,root);
			low[u]=std::min(low[v],low[u]);
			if(low[v]>=dfn[u]&&u!=root) cut[u]=1;
			cnt++;
		}
		low[u]=std::min(low[u],dfn[v]);
	}
	if(cnt>1&&u==root) cut[u]=1;
}
  • 最大流
#define Type int
#define _INF _INT_INF
struct Graph{
	int fir[N],_fir[N],nex[M],to[M],tot;
	Type w[M];
	inline void add(int u,int v,Type c,int flag=1){
		to[++tot]=v;nex[tot]=fir[u];fir[u]=tot;w[tot]=c;
		if(flag) add(v,u,0,0);
	}
}G;
int n,S,T;
int deep[N];
int left,right,que[N];
inline int bfs(){
	__builtin_memset(deep,0,(n+1)*sizeof deep[0]);
	left=right=0;que[0]=S;deep[S]=1;
	int u;
	while(left<=right){
		u=que[left++];
		for(int v,i=G.fir[u];i;i=G.nex[i]){
			v=G.to[i];
			if(deep[v]||!G.w[i]) continue;
			deep[v]=deep[u]+1;que[++right]=v;
			if(v==T) return 1;
		}
	}
	return 0;
}
Type dfs(int u,Type now=_INF){
	if(u==T) return now;
	Type res=now;
	for(int v,&i=G._fir[u];i;i=G.nex[i]){
		v=G.to[i];
		if(deep[v]!=deep[u]+1||!G.w[i]) continue;
		Type k=dfs(v,lib::min(res,G.w[i]));
		if(!k) deep[v]=0;
		else G.w[i]-=k,G.w[i^1]+=k,res-=k;
		if(!res) break;
	}
	return now-res;
}
inline Type dinic(){
	Type ans=0;
	while(bfs()){
		Type now;
		__builtin_memcpy(G._fir,G.fir,(n+1)*sizeof G.fir[0]);
		while(now=dfs(S)) ans+=now;
	}
	return ans;
}
  • 费用流
#define Type int
#define _INF _INT_INF
int n,m,S,T;
Graph G;
Type mincost,maxflow,h[N];
int vis[N];
inline void spfa(){
	static int que[M*10],left,right;
	__builtin_memset(h,0x3f,sizeof h);
	h[S]=0;vis[S]=1;
	left=0;right=-1;que[++right]=S;
	int u,i,v;
	while(left<=right){
		u=que[left++];vis[u]=0;
		for(i=G.fir[u];i;i=G.nex[i]){
			v=G.to[i];
			if(!G.w[i]||h[v]<=h[u]+G.c[i]) continue;
			h[v]=h[u]+G.c[i];
			if(!vis[v]) que[++right]=v,vis[v]=1;
		}
	}
}
Type dfs(int u,Type want=_INF){
	if(u==T) return mincost+=(h[S]-h[T])*want,maxflow+=want,want;
	vis[u]=1;
	Type last=want;
	for(int v,&i=G._fir[u];i;i=G.nex[i]){
		v=G.to[i];
		if(!G.w[i]||vis[v]||G.c[i]!=h[u]-h[v]) continue;
		Type k=dfs(v,std::min(last,G.w[i]));
		G.w[i]-=k;G.w[i^1]+=k;last-=k;
		if(!last) break;
	}
	return want-last;
}
inline int relable(){
	Type d=_INF;
	for(int i=1;i<=n;i++)if(vis[i])
		for(int j=G.fir[i];j;j=G.nex[j])if(G.w[j]&&!vis[G.to[j]]) d=std::min(d,G.c[j]-h[i]+h[G.to[j]]);
	if(d==_INF) return 0;
	for(int i=1;i<=n;i++)if(vis[i]) h[i]+=d;
	return 1;
}
inline void zkw(){
	spfa();
	do{
		do{
			__builtin_memset(vis,0,sizeof vis);__builtin_memcpy(G._fir,G.fir,sizeof G._fir);
		}while(dfs(S));
	}while(relable());
}
  • 点分治(点分树)

  • 支配树

Graph G,H,T;
int dfscnt,dfn[N],id[N],fa[N];
int idom[N],sdom[N];
struct UnionSet{
	int fa[N],min[N];
	inline int find(int k){
		if(fa[k]==k) return k;
		int father=find(fa[k]);
		if(dfn[sdom[min[fa[k]]]]<dfn[sdom[min[k]]]) min[k]=min[fa[k]];
		return fa[k]=father;
	}
}S;
void dfs(int u){
	dfn[u]=++dfscnt;id[dfscnt]=u;
	for(int i=G.fir[u];i;i=G.nex[i])if(!dfn[G.to[i]]) fa[G.to[i]]=u,dfs(G.to[i]);
}
inline void build(int root){
	dfs(root);
	for(int i=1;i<=dfscnt;i++) sdom[i]=S.fa[i]=S.min[i]=i;
	for(int u,i=dfscnt;i>1;i--){
		u=id[i];
		for(int v,j=T.fir[u];j;j=T.nex[j])if(dfn[T.to[j]]){
			v=T.to[j];S.find(v);
			if(dfn[sdom[S.min[v]]]<dfn[sdom[u]]) sdom[u]=sdom[S.min[v]];
		}
		S.fa[u]=fa[u];
		H.add(sdom[u],u);u=fa[u];
		for(int v,j=H.fir[u];j;j=H.nex[j]){
			v=H.to[j];S.find(v);
			idom[v]=(u==sdom[S.min[v]])?u:S.min[v];
		}
		H.fir[u]=0;
	}
	for(int u,i=2;i<=dfscnt;i++){
		u=id[i];
		if(idom[u]^sdom[u]) idom[u]=idom[idom[u]];
	}
}
  • 2-SAT,差分约束

  • LGV 引理

  • 矩阵树定理,BEST 定理

  • 图匹配

  • 最小树形图

  • 原根

  • 长链剖分

  • 高斯消元

需要求逆元:

inline ModInt det(int n,ModInt (*a)[N]){
	ModInt ans;ans=1;
	for(int i=1;i<=n;i++){
		if(!a[i][i].x){
			ans=0-ans;
			for(int k=i+1;k<=n;k++)if(a[k][i].x){std::swap(a[i],a[k]);goto CONTINUE;}
			return {0};
		}
	CONTINUE:
		ans*=a[i][i];
		for(int k=i+1;k<=n;k++)if(a[k][i].x){
			ModInt o=a[k][i]/a[i][i];
			for(int j=i;j<=n;j++) a[k][j]-=a[i][j]*o;
		}
	}
	return ans;
}

不需要逆元:

inline ModInt det(){
	ModInt ans;ans=1;
	for(int i=1;i<=n;i++){
		for(int j=i+1;j<=n;j++){
			while(a[j][i]){
				long long k=a[i][i]/a[j][i];
				for(int h=1;h<=n;h++) a[i][h]-=k*a[j][h];
				std::swap(a[i],a[j]);
				ans=-ans;
			}
		}
	}
	for(int i=1;i<=n;i++) ans*=a[i][i];
	return ans;
}
  • manacher, kmp

  • AC 自动机

struct Node{
	Node *son[26],*fail;
	int cnt;
}addr[N],*root=addr,*tot=root+1;
inline void insert(char *s){
	Node *tree=root;
	for(int num,i=1;s[i];i++){
		num=s[i]-'a';
		if(!tree->son[num]) tree->son[num]=tot++;
		tree=tree->son[num];tree->cnt++;
	}
}
inline void build(){
	static Node *que[N];int left=0,right=-1;
	root->fail=root;
	for(int i=0;i<26;i++){
		if(root->son[i]) root->son[i]->fail=root,que[++right]=root->son[i];
		else root->son[i]=root;
	}
	Node *u;
	while(left<=right){
		u=que[left++];
		for(int i=0;i<26;i++){
			if(u->son[i]){
				u->son[i]->fail=u->fail->son[i];
				que[++right]=u->son[i];
			}
			else u->son[i]=u->fail->son[i];
		}
	}
}
  • PAM

  • SAM

struct Node{
	Node *son[26];
	int len,cnt;
	Node *link;
}dizhi[N*2],*root=&dizhi[0],*last=root;
int tot;
inline void add(int c){
	Node *p=last,*now=&dizhi[++tot];
	now->len=p->len+1;now->cnt=1;
	for(;p&&!p->son[c];p=p->link) p->son[c]=now;
	if(!p) now->link=root;
	else{
		Node *q=p->son[c];
		if(q->len==p->len+1) now->link=q;
		else{
			Node *clone=&dizhi[++tot];*clone=*q;
			clone->len=p->len+1;clone->cnt=0;
			q->link=now->link=clone;
			for(;p&&p->son[c]==q;p=p->link) p->son[c]=clone;
		}
	}
	last=now;
}
  • crt,Lucas 定理,(扩展)欧拉定理,(扩展)BSGS

  • 各种筛法

  • FWT

inline void Or(int n,long long *f){for(int h=1;h<n;h<<=1)for(int i=0;i<n;i+=h<<1)for(int j=0;j<h;j++) f[i+j+h]+=f[i+j];}
inline void IOr(int n,long long *f){for(int h=1;h<n;h<<=1)for(int i=0;i<n;i+=h<<1)for(int j=0;j<h;j++) f[i+j+h]-=f[i+j];}
inline void And(int n,long long *f){for(int h=1;h<n;h<<=1)for(int i=0;i<n;i+=h<<1)for(int j=0;j<h;j++) f[i+j]+=f[i+j+h];}
inline void IAnd(int n,long long *f){for(int h=1;h<n;h<<=1)for(int i=0;i<n;i+=h<<1)for(int j=0;j<h;j++) f[i+j]-=f[i+j+h];}
inline void Xor(int n,long long *f){
	for(int h=1;h<n;h<<=1)for(int i=0;i<n;i+=h<<1)for(int j=0;j<h;j++)
		f[i+j]+=f[i+j+h],f[i+j+h]=f[i+j]-f[i+j+h]-f[i+j+h];
}
inline void IXor(int n,long long *f){
	for(int h=1;h<n;h<<=1)for(int i=0;i<n;i+=h<<1)for(int j=0;j<h;j++)
		f[i+j]+=f[i+j+h],f[i+j+h]=f[i+j]-f[i+j+h]-f[i+j+h],f[i+j]*=inv2,f[i+j+h]*=inv2;
}
  • 线性基

  • 辛普森积分

posted @ 2022-06-17 15:29  suxxsfe  阅读(16)  评论(0编辑  收藏  举报