模板库

缺省源

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<map>
#include<set>
#include<queue>
#include<ctime>
#include<assert.h>
#define _INT_INF ((int)0x3f3f3f3f)
#define _UINT_MAX ((unsigned int)0xffffffff)
#define _INT_MAX ((int)0x7fffffff)
#define _LL_INF ((long long)0x3f3f3f3f3f3f3f3f)
#define _ULL_MAX ((unsigned long long)0xffffffffffffffff)
#define _LL_MAX ((long long)0x7fffffffffffffff)
namespace FastIO{
	#define BUF_SIZE 33554432
	char buff[BUF_SIZE];char *p1=buff,*p2=buff;
	#define getChar (p1==p2&&(p2=(p1=buff)+fread(buff,1,BUF_SIZE,stdin),p1==p2)?EOF:*p1++)
	__attribute__((always_inline))inline int read(){
		register int x=0;register char c=getChar;
		while(c<'0'||c>'9')	c=getChar;while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getChar;return x;
	}
	__attribute__((always_inline))inline int reads(){
		register int x=0,y=1;register char c=getChar;
		while(c<'0'||c>'9') y&=(c!='-'),c=getChar;while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getChar;return y?x:-x;
	}
	__attribute__((always_inline))inline long long readl(){
		register long long x=0;register char c=getChar;
		while(c<'0'||c>'9') c=getChar;while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getChar;return x;
	}
	__attribute__((always_inline))inline int readsl(){
		register long long x=0;register int y=1;register char c=getChar;
		while(c<'0'||c>'9') y&=(c!='-'),c=getChar;while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getChar;return y?x:-x;
	}
	__attribute__((always_inline))inline void read(char *s){
		register char c=getChar;while(c=='
'||c=='
'||c==' '||c=='	') c=getChar;
        while(c!='
'&&c!='
'&&c!=' '&&c!='	'&&c!=EOF) *s=c,s++,c=getChar;*s=0;
	}
	#undef getChar
	#define EN write('
')
	#define SPACE write(' ')
	char buffW[BUF_SIZE];int bb;
	char stack[28];
	__attribute__((always_inline))inline void write(register int x,register short base=10){
		if(!x) return buffW[bb++]='0',void();if(x<0) buffW[bb++]='-',x=-x;
		register short top=0;
		while(x) stack[++top]=(x%base)^48,x/=base;while(top) buffW[bb++]=stack[top--];
	}
	__attribute__((always_inline))inline void writeEN(register int x,register short base=10){
		if(!x) return buffW[bb++]='0',buffW[bb++]='
',void();if(x<0) buffW[bb++]='-',x=-x;
		register short top=0;
		while(x) stack[++top]=(x%base)^48,x/=base;while(top) buffW[bb++]=stack[top--];buffW[bb++]='
';
	}
	__attribute__((always_inline))inline void writeSP(register int x,register short base=10){
		if(!x) return buffW[bb++]='0',buffW[bb++]=' ',void();if(x<0) buffW[bb++]='-',x=-x;
		register short top=0;
		while(x) stack[++top]=(x%base)^48,x/=base;while(top) buffW[bb++]=stack[top--];buffW[bb++]=' ';
	}
	__attribute__((always_inline))inline void write(register long long x,register short base=10){
		if(!x) return buffW[bb++]='0',void();if(x<0) buffW[bb++]='-',x=-x;
		register short top=0;
		while(x) stack[++top]=(x%base)^48,x/=base;while(top) buffW[bb++]=stack[top--];
	}
	__attribute__((always_inline))inline void writeEN(register long long x,register short base=10){
		if(!x) return buffW[bb++]='0',buffW[bb++]='
',void();if(x<0) buffW[bb++]='-',x=-x;
		register short top=0;
		while(x) stack[++top]=(x%base)^48,x/=base;while(top) buffW[bb++]=stack[top--];buffW[bb++]='
';
	}
	__attribute__((always_inline))inline void writeSP(register long long x,register short base=10){
		if(!x) return buffW[bb++]='0',buffW[bb++]=' ',void();if(x<0) buffW[bb++]='-',x=-x;
		register short top=0;
		while(x) stack[++top]=(x%base)^48,x/=base;while(top) buffW[bb++]=stack[top--];buffW[bb++]=' ';
	}
	__attribute__((always_inline))inline void write(register char c){buffW[bb++]=c;}
	__attribute__((always_inline))inline void write(const char *c){while(*c) buffW[bb++]=*c,c++;}
	#define SUC_RETURN fwrite(buffW,1,bb,stdout),0
	#undef BUF_SIZE
}//namespace FastIO
using namespace FastIO;
namespace lib{
	__attribute__((always_inline))inline void chkMin(int &a,const int &b){(a>b)&&(a=b);}
	__attribute__((always_inline))inline void chkMin(long long &a,const long long &b){(a>b)&&(a=b);}
	__attribute__((always_inline))inline void chkMax(int &a,const int &b){(a<b)&&(a=b);}
	__attribute__((always_inline))inline void chkMax(long long &a,const long long &b){(a<b)&&(a=b);}
	__attribute__((always_inline))inline int min(const int &a,const int &b){return a>b?b:a;}
	__attribute__((always_inline))inline long long min(const long long &a,const long long &b){return a>b?b:a;}
	__attribute__((always_inline))inline int max(const int &a,const int &b){return a>b?a:b;}
	__attribute__((always_inline))inline long long max(const long long &a,const long long &b){return a>b?a:b;}
	__attribute__((always_inline))inline void swap(int &a,int &b){a^=b;b^=a;a^=b;}
	__attribute__((always_inline))inline void swap(long long &a,long long &b){a^=b;b^=a;a^=b;}
	__attribute__((always_inline))inline int abs(const int &a){return a>0?a:-a;}
	__attribute__((always_inline))inline long long abs(const long long &a){return a>0?a:-a;}
}
int main(){
	return SUC_RETURN;
}

图论

邻接表

struct Graph{
	int fir[N],nex[M],to[M],tot;
	inline void add(int u,int v,int flag=1){
		to[++tot]=v;
		nex[tot]=fir[u];fir[u]=tot;
		if(flag) add(v,u,0);
	}
	inline void clear(){std::memset(fir,0,sizeof fir);tot=0;}
}G;

dij 最短路

inline void dij(int u,int *dis,const Graph &G=::G){
	std::memset(dis,0x3f,(n+1)*sizeof dis[0]);dis[u]=0;
	static std::priority_queue<std::pair<int,int> >que;
	que.push(std::make_pair(0,u));
	while(!que.empty()){
		u=que.top().second;
		if(que.top().first^(-dis[u])){que.pop();continue;}
		que.pop();
		for(int v,i=G.fir[u];i;i=G.nex[i]){
			v=G.to[i];
			if(dis[v]<=dis[u]+G.w[i]) continue;
			dis[v]=dis[u]+G.w[i];que.push(std::make_pair(-dis[v],v));
		}
	}
}

tarjan 缩强连通分量

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 求割点

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;
}

tarjan 求桥

void tarjan(int u){
	dfn[u]=low[u]=++dfscnt;
	for(int v,i=G.fir[u];i;i=G.nex[i]){
		v=G.to[i];
		if(!dfn[v]){
			fa[v]=u;tarjan(v);
			low[u]=std::min(low[u],low[v]);
			if(low[v]>dfn[u]) bridge[v]=1,ans++;
		}
		else if(v!=fa[u]) low[u]=std::min(low[u],dfn[v]);
	}
}

dinic

int n,m,S,T;
int deep[N];
int left,right,que[N];
inline int bfs(){
	std::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;
}
long long dfs(int u,long long now=1e18){
	if(u==T) return now;
	long long 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;
		long long k=dfs(v,std::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 long long dinic(){
	long long ans=0;
	while(bfs()){
		long long now;
		std::memcpy(G.fir_,G.fir,(n+1)*sizeof G.fir[0]);
		while(now=dfs(S)) ans+=now;
	}
	return ans;
}

最小费用最大流

int n,m,S,T;
long long dis[N],h[N];
int pre_edge[N],pre_node[N];
std::priority_queue<std::pair<long long,int> >pque;
inline void dij(){
	std::memset(dis,0x3f,sizeof dis);dis[S]=0;
	while(!pque.empty()) pque.pop();
	pque.push(std::make_pair(0,S));
	int u,i,v;
	while(!pque.empty()){
		u=pque.top().second;
		if(dis[u]!=-pque.top().first){pque.pop();continue;}
		pque.pop();
		if(u==T) break;
		for(i=G.fir[u];i;i=G.nex[i]){
			v=G.to[i];
			long long len=G.c[i]+h[u]-h[v];
			if(!G.w[i]||dis[v]<=dis[u]+len) continue;
			dis[v]=dis[u]+len;
			preNode[v]=u;preEdge[v]=i;
			pque.push(std::make_pair(-dis[v],v));
		}
	}
}
int in[N],left,right,que[N*20];
inline void spfa(){
	left=right=0;que[0]=S;
	std::memset(h,0x3f,sizeof h);
	h[S]=0;in[S]=1;
	int u,i,v;
	while(left<=right){
		u=que[left++];in[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(!in[v]) que[++right]=v,in[v]=1;
		}
	}
}
long long maxflow,ans;
inline void work(int n){
	spfa();
	for(;;){
		dij();
		if(dis[T]==LL_INF) break;
		long long minflow=LL_INF;
		for(int i=T;i^S;i=pre_node[i]) minflow=std::min(minflow,G.w[pre_edge[i]]);
		for(int i=T;i^S;i=pre_node[i]) G.w[pre_edge[i]]-=minflow,G.w[pre_edge[i]^1]+=minflow;
		maxflow+=minflow;ans+=minflow*(dis[T]+h[T]);
		for(int i=1;i<=n;i++) h[i]=std::min(h[i]+dis[i],LL_INF);
	}
}

有源汇上下界最大流

long long d[N];
inline void add(int u,int v,long long l,long long r){
	G.add(u,v,r-l);
	d[u]-=l;d[v]+=l;
}
int main(){
	int s=n+1,t=s+1;
	S=t+1;T=S+1;
	long long sum=0;
	for(int i=1;i<=t;i++){
		if(d[i]>0) G.add(S,i,d[i]),sum+=d[i];
		else if(d[i]<0) G.add(i,T,-d[i]);
	}
	G.add(t,s,LL_INF);
	if(dinic()^sum) puts("-1
");
	else{
		for(int i=G.fir[S];i;i=G.nex[i]) G.w[i]=G.w[i^1]=0;
		for(int i=G.fir[T];i;i=G.nex[i]) G.w[i]=G.w[i^1]=0;
		sum=G.w[G.tot];G.w[G.tot]=G.w[G.tot-1]=0;
		S=s;T=t;
		printf("%lld

",sum+dinic());
	}
	return 0;
}

最小割树

Graph G,T; 
struct Flow{
	int S,T;
	int deep[N];
	int left,right,que[N];
	inline int bfs(){
		std::memset(deep,0,sizeof deep);
		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;
	}
	int dfs(int u,int now=INT_INF){
		if(u==T) return now;
		int 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;
			int k=dfs(v,std::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 void init(){
		for(int i=2;i<=G.tot;i+=2){
			G.w[i]+=G.w[i^1];
			G.w[i^1]=0;
		}
	}
	inline int dinic(int s,int t){
		init();S=s;T=t;
		int ans=0,now=0;
		while(bfs()){
			std::memcpy(G.fir_,G.fir,sizeof G.fir);
			while(now=dfs(s)) ans+=now;
		}
		return ans;
	}
}F;
int min[11][N],fa[11][N],deep[N];
int node[N],tmp1[N],tmp2[N];
void build(int l,int r){
	if(l==r) return;
	int s=node[l],t=node[l+1];
	int cut=F.dinic(s,t);
	T.add(s,t,cut);T.add(t,s,cut);
	int cnt1=0,cnt2=0;
	for(int i=l;i<=r;i++){
		if(F.deep[node[i]]) tmp1[++cnt1]=node[i];
		else tmp2[++cnt2]=node[i];
	}
	for(int i=l;i<l+cnt1;i++) node[i]=tmp1[i-l+1];
	for(int i=l+cnt1;i<=r;i++) node[i]=tmp2[i-cnt1-l+1];
	build(l,l+cnt1-1);build(l+cnt1,r);
}

HLPP 最大流

int S,T;
int left,right,que[N*100];
int in[N];
int h[N],cnth[N*2];
long long res[N];
inline void bfs(){
	std::memset(h,0x3f,sizeof h);h[T]=0;
	left=right=0;que[0]=T;in[T]=1;
	int u;
	while(left<=right){
		u=que[left++];in[u]=0;
		for(int v,i=G.fir[u];i;i=G.nex[i]){
			v=G.to[i];
			if(!G.w[i^1]||h[v]<=h[u]+1) continue;
			h[v]=h[u]+1;
			if(!in[v]) que[++right]=v,in[v]=1;
		}
	}
}
inline int pqueCmp(const int &a,const int &b){return h[a]<h[b];}
std::priority_queue<int,std::vector<int>,int(*)(const int &a,const int &b)>pque(pqueCmp);
inline void push(int u){
	for(int v,i=G.fir[u];i;i=G.nex[i]){
		v=G.to[i];
		if(h[v]+1!=h[u]||!G.w[i]) continue;
		long long k=std::min(G.w[i],res[u]);
		G.w[i]-=k;G.w[i^1]+=k;
		res[u]-=k;res[v]+=k;
		if(!in[v]&&v!=T&&v!=S) in[v]=1,pque.push(v);
		if(!res[u]) break;
	}
}
inline void relabel(int u){
	h[u]=INT_INF;
	for(int v,i=G.fir[u];i;i=G.nex[i]){
		v=G.to[i];
		if(G.w[i]) h[u]=std::min(h[u],h[v]+1);
	}
}
inline long long hlpp(int s,int t){
	S=s;T=t;
	bfs();
	if(h[S]==INT_INF) return 0;
	h[S]=n;
	for(int i=1;i<=n;i++)if(h[i]<INT_INF) cnth[h[i]]++;
	for(int v,i=G.fir[S];i;i=G.nex[i]){
		v=G.to[i];
		if(G.w[i]&&h[v]<INT_INF){
			res[S]-=G.w[i];res[v]+=G.w[i];
			G.w[i^1]+=G.w[i];G.w[i]=0;
			if(!in[v]&&v!=T&&v!=S) pque.push(v),in[v]=1;
		}
	}
	int u;
	while(!pque.empty()){
		u=pque.top();pque.pop();in[u]=0;
		push(u);
		if(res[u]){
			if(!--cnth[h[u]]){
				for(int i=1;i<=n;i++)if(h[i]>h[u]&&i!=S&&i!=T) h[i]=n+1;
			}
			relabel(u);cnth[h[u]]++;
			pque.push(u);in[u]=1;
		}
	}
	return res[T];
}

Stoer-Wagner 求无向图最小割

int S,T;
int w[N],inA[N];
int del[N],dis[N][N];
inline int mincut(int x){
	std::memset(w,0,sizeof w);std::memset(inA,0,sizeof inA);
	w[0]=-1;
	for(int id,i=1;i<=n-x+1;i++){
		id=0;
		for(int j=1;j<=n;j++)if(!inA[j]&&!del[j]&&w[j]>w[id]) id=j;
		inA[id]=1;
		if(i==n-x) S=id;
		else if(i==n-x+1) T=id;
		for(int j=1;j<=n;j++)if(!inA[j]&&!del[j]) w[j]+=dis[id][j];
	}
	return w[T];
}
inline int sw(){
	int ret=1e9;
	for(int i=1;i<n;i++){
		ret=std::min(ret,mincut(i));
		del[T]=1;
		for(int j=1;j<=n;j++) dis[S][j]+=dis[T][j],dis[j][S]+=dis[j][T];
	}
	return ret;
}

tarjan 最小树形图

int uniFa[N];
inline int find(int k){return k==uniFa[k]?k:uniFa[k]=find(uniFa[k]);}
struct Edge{
	int u,v,w,w0;
};
struct Node{
	Node *ls,*rs,*root;
	int deep,tag;
	Edge *edge;
	inline void pushdown(){
		ls->tag+=tag;rs->tag+=tag;
		edge->w+=tag;
		tag=0;
	}
}nullNode,*null=&nullNode;
int tot;
inline void New(Node *&x,Edge *e){
	x=new Node;
	x->deep=1;x->tag=0;
	x->ls=x->rs=null;
	x->root=x;x->edge=e;
}
Node *merge(Node *x,Node *y){
	if(x==null) return y;
	if(y==null) return x;
	if(x->edge->w+x->tag>y->edge->w+y->tag) std::swap(x,y);
	x->pushdown();
	x->rs=merge(x->rs,y);
	if(x->ls->deep<x->rs->deep) std::swap(x->ls,x->rs);
	x->deep=x->rs->deep+1;
	x->ls->root=x->rs->root=x;
	return x;
}
inline void pop(Node *&x){
	x->pushdown();
	Node *ls=x->ls,*rs=x->rs;
	delete x;
	x=merge(ls,rs);
}
int n,m;
int vis[N],fa[N];
int nex[N];
Edge *in[M],edge[M];
Node *p[N];
inline void contraction(){
	for(int i=1;i<=n;i++) p[i]=null,uniFa[i]=i;
	for(int i=1;i<=m;i++){
		Node *tmp;
		New(tmp,&edge[i]);
		p[edge[i].v]=merge(p[edge[i].v],tmp);
	}
	vis[1]=1;
	for(int u=1,pre=1,o;p[u];pre=u,vis[u]=1){
		do{
			in[u]=p[u]->edge;pop(p[u]);
			u=find(in[u]->u);
		}while(u==pre&&p[u]!=null);
		if(u==pre) break;
		if(!vis[u]) continue;
		p[++n]=null;uniFa[n]=n;
		for(pre=u;u^n;){
			uniFa[u]=fa[u]=n;
			if(p[u]!=null) p[u]->tag-=in[u]->w;
			p[n]=merge(p[n],p[u]);
			o=find(in[u]->u);
			nex[o==n?pre:o]=u;
			u=o;
		}
	}
}
int expand(int,int);
int expand(int u){
	int ans=0;
	for(int x=nex[u];x^u;x=nex[x]){
		if(in[x]->w0==INT_INF) return INT_INF;
		if((ans+=in[x]->w0+expand(in[x]->v,x))>=INT_INF) return INT_INF;
	}
	return ans;
}
inline int expand(int u,int goal){
	int ans=0;
	for(;u^goal;u=fa[u])
		if((ans+=expand(u))>=INT_INF) return INT_INF;
	return ans;
}
int main(){
	n=read();m=read();int root=read();
	for(int i=1;i<=m;i++) edge[i].u=read(),edge[i].v=read(),edge[i].w=edge[i].w0=read();
	for(int i=1;i<n;i++) edge[++m]={i,i+1,INT_INF,INT_INF};
	edge[++m]={n,1,INT_INF,INT_INF};
	contraction();
	int ans=expand(root,n);
	printf("%d
",ans==INT_INF?-1:ans);
	return 0;
}

spfa 找负环

int dis[N],cnt[N];
int left,right,que[N];
inline int spfa(){
	std::memset(dis,0x3f,sizeof dis);std::memset(cnt,0,sizeof cnt);
	right=left=0;que[0]=1;
	dis[1]=0;
	int u,v,i;
	while(left<=right){
		u=que[left++];
		for(i=G.fir[u];i;i=G.nex[i]){
			v=G.to[i];
			if(dis[v]>dis[u]+G.w[i]){
				dis[v]=dis[u]+G.w[i];
				cnt[v]++;
				if(cnt[v]>n) return 1;
				que[++right]=v;
			}
		}
	}
	return 0;
}

支配树

Graph G,H,T;
int uni[N],min[N];
int dfscnt,dfn[N],id[N],fa[N];
int sdom[N],idom[N];
inline int find(int k){
	if(k==uni[k]) return k;
	int ret=find(uni[k]);
	if(dfn[sdom[min[uni[k]]]]<dfn[sdom[min[k]]]) min[k]=min[uni[k]];
	return uni[k]=ret;
}
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 work(int s){
	dfs(s);
	for(int i=1;i<=n;i++) sdom[i]=uni[i]=min[i]=i;
	for(int u,i=dfscnt;i>1;i--){
		u=id[i];
		for(int v,i=H.fir[u];i;i=H.nex[i]){
			v=H.to[i];
			if(!dfn[v]) continue;
			find(v);
			if(dfn[sdom[min[v]]]<dfn[sdom[u]]) sdom[u]=sdom[min[v]];
		}
		uni[u]=fa[u];
		T.add(sdom[u],u);u=fa[u];
		for(int v,i=T.fir[u];i;i=T.nex[i]){
			v=T.to[i];
			find(v);idom[v]=(u==sdom[min[v]])?u:min[v];
		}
		T.fir[u]=0;
	}
	for(int u,i=2;i<=dfscnt;i++){
		u=id[i];
		if(idom[u]^sdom[u]) idom[u]=idom[idom[u]];
	}
}
int ans[N];
inline void get_ans(){
	for(int i=dfscnt;i>1;i--) ans[idom[id[i]]]+=++ans[id[i]];
	ans[id[1]]++;
}

LGV 引理

匈牙利

int match[N],vis[N];
int dfs(int u){
	for(int v,i=G.fir[u];i;i=G.nex[i]){
		v=G.to[i];
		if(vis[v]) continue;
		vis[v]=1;
		if(!match[v]||dfs(match[v])) return match[v]=u,match[u]=v,1;
	}
	return 0;
}

二分图最大权匹配 KM

int num_left,num_right;
int G[N][N];
int vis[N],pre[N],match[N],lw[N],d[N];
int que[N],tail,head;
inline int bfs(int u){
    tail=head=0;que[0]=u;
    pre[u]=0;
    while(tail<=head){
        u=que[tail++];vis[u]=1;
        for(int i=num_left+1;i<=num_right;i++)if(G[u][i]==lw[u]+lw[i]){
            if(vis[i]) continue;
            vis[i]=1;
            if(match[i]) pre[match[i]]=u,que[++head]=match[i];
            else{
                int d=u,e=i,t;
                while(d){
                    t=match[d];
                    match[d]=e;match[e]=d;
                    d=pre[d];e=t; 
                }
                return 1;
            }
        }
    }
    return 0;
}
inline LL max_match(){
    for(int i=1;i<=num_left;i++){
        for(int j=num_left+1;j<=num_right;j++) lw[i]=std::max(lw[i],G[i][j]);
    }
    for(int i=1;i<=num_left;i++){
        std::memset(vis,0,sizeof vis);std::memset(d,0x3f,sizeof d);
        if(bfs(i)) continue;
        for(int j=1;j<=num_left;j++)if(vis[j])
            for(int k=num_left+1;k<=num_right;k++)
                if(!vis[k]) d[k]=std::min(d[k],lw[j]+lw[k]-G[j][k]);
        while(1){
            int now=INT_INF,to,s;
            for(int j=num_left+1;j<=num_right;j++)if(!vis[j]) now=std::min(now,d[j]);
            for(int j=1;j<=num_left;j++)if(vis[j]) lw[j]-=now;
            for(int j=num_left+1;j<=num_right;j++)
                if(vis[j]) lw[j]+=now;
                else d[j]-=now,to=d[j]?to:j;
            if(!match[to]) break;
            s=match[to];vis[to]=vis[s]=1;//打上 vis 标记
            for(int j=num_left+1;j<=num_right;j++)if(!vis[j]) d[j]=std::min(d[j],lw[s]+lw[j]-G[s][j]);
        }
        std::memset(vis,0,sizeof vis);
        bfs(i);
    }
    long long ans=0;
    for(int i=1;i<=num_right;i++) ans+=lw[i];
    return ans; 
}

树的最小表示法

struct Center{int a,b;};
int size[N],maxson[N];
void getMaxs(int u,int fa,int n,const Graph &G){
	size[u]=1;maxson[u]=0;
	for(int v,i=G.fir[u];i;i=G.nex[i]){
		v=G.to[i];
		if(v==fa) continue;
		getMaxs(v,u,n,G);
		size[u]+=size[v];maxson[u]=std::max(maxson[u],size[v]);
	}
	maxson[u]=std::max(maxson[u],n-size[u]);
}
inline Center getCenter(int n,const Graph &G){
	getMaxs(1,0,n,G);
	int min=1e9;
	for(int i=1;i<=n;i++) min=std::min(maxson[i],min);
	Center ret={0,0};
	for(int i=1;i<=n;i++)if(maxson[i]==min) (ret.a?ret.b:ret.a)=i;
	return ret;
}
int fa[N];
std::vector<int>p[N];
int dfs(int u,int deep,const Graph &G){
	p[deep].push_back(u);
	int ret=deep;
	for(int v,i=G.fir[u];i;i=G.nex[i]){
		v=G.to[i];
		if(v==fa[u]) continue;
		fa[v]=u;
		ret=std::max(ret,dfs(v,deep+1,G));
	}
	return ret;
}
int tag[N];
std::vector<int>sonTag[N];
inline void getans(int u,int *ans,const Graph &G){
	ans[++ans[0]]=0;
	std::vector<int>v;
	for(int i=G.fir[u];i;i=G.nex[i])if(G.to[i]^fa[u]) v.push_back(G.to[i]);
	std::sort(v.begin(),v.end(),[](const int &a,const int &b){return tag[a]<tag[b];});
	for(int j=0,sz=v.size();j<sz;j++) getans(v[j],ans,G);
	ans[++ans[0]]=1;
}
inline int ahu(int n,const Graph &G,int root,int *ans){
	for(int i=1;i<=n;i++) p[i].clear(),sonTag[i].clear();
	fa[root]=0;int h=dfs(root,1,G);
	for(int j=0,sz=p[h].size();j<sz;j++) tag[p[h][j]]=0;
	int tot=0;
	for(int i=h-1;i;i--){
		for(int j=0,sz=p[i+1].size(),v;j<sz;j++){
			v=p[i+1][j];
			sonTag[fa[v]].push_back(tag[v]);
		}
		std::sort(p[i].begin(),p[i].end(),[](const int &a,const int &b){return sonTag[a]<sonTag[b];});
		for(int j=0,sz=p[i].size(),u;j<sz;j++){
			u=p[i][j];
			if(j&&sonTag[u]!=sonTag[p[i][j-1]]) tot++;
			tag[u]=tot;
		}
	}
	getans(root,ans,G);
	return h;
}

点分治

int root,sum;
void find(int x,int fa=0){
	size[x]=1;max[x]=0;
	for(int v,i=G.fir[x];i;i=G.nex[i]){
		v=G.to[i];
		if(v==fa||vis[v]) continue;
		find(v,x);
		size[x]+=size[v];
		if(max[x]<size[v]) max[x]=size[v];
	}
	if(max[x]<sum-size[x]) max[x]=n-size[x];
	if(max[x]<max[root]) root=x;
}
inline void calc(int u){
	
}
void divide(int u){
	vis[u]=1;
	calc(u);
	for(int v,i=G.fir[u];i;i=G.nex[i]){
		v=G.to[i];
		if(vis[v]) continue;
		root=0;sum=size[v];
		find(v);find(root);
		divide(root);
	}
}
int main(){
	max[0]=INT_INF;sum=n;
	find(1);find(root);
	divide(root);
	return 0;
}

数据结构

普通堆

使用 std::priority_queue

使用自定义函数重载 std::setstd::priority_queue 等的比较

函数指针

inline int pqueCmp(const int &a,const int &b){return a>b;}
std::priority_queue<int,std::vector<int>,int(*)(const int &a,const int &b)>pque(pqueCmp);

lambda 函数

auto pqueCmp=[](const int &a,const int &b){return a>b;};
std::priority_queue<int,std::vector<int>,decltype(pqueCmp)>pque(pqueCmp);

并查集

int fa[N];
int find(int k){return fa[k]==k?k:fa[k]=find(fa[k]);}
inline void link(int x,int y){
	x=find(x);y=find(y);
	if(x!=y) fa[x]=y;
}

树状数组

int tree[N];
#define lowbit(x) (x&(-x))
inline void add(int pos,int k){for(;pos<=n;pos+=lowbit(pos)) tree[pos]+=k;}
inline int ask(int pos){
	int ans=0;
	for(;pos;pos-=lowbit(pos)) ans+=tree[pos];
	return ans;
}

线段树

struct Node{
	Node *ls,*rs;
	int tag;
	inline void pushup(){}
	inline void pushdown(){}
}dizhi[N*2],*root=&dizhi[0];int tot=0;
void build(Node *&tree,int l,int r){
	tree=&dizhi[++tot];
	if(l==r) return;
	int mid=(l+r)>>1;
	build(tree->ls,l,mid);build(tree->rs,mid+1,r);
	tree->pushup();
}
void change(Node *tree,int l,int r,int pos){
	if(l==r) return;
	tree->pushdown();
	int mid=(l+r)>>1;
	pos<=mid?change(tree->ls,l,mid,pos):change(tree->rs,mid+1,r,pos);
	tree->pushup();
}
void change(Node *tree,int l,int r,int ql,int qr){
	if(ql<=l&&r<=qr) return;
	tree->pushdown();
	int mid=(l+r)>>1;
	if(ql<=mid) change(tree->ls,l,mid,ql,qr,k);
	if(qr>mid) change(tree->rs,mid+1,r,ql,qr,k);
	tree->pushup();
}
Data ask(Node *tree,int l,int r,int ql,int qr){
	if(ql<=l&&r<=qr) return tree->x;
	tree->pushdown();
	int mid=(l+r)>>1;
	if(qr<=mid) return ask(tree->ls,l,mid,ql,qr);
	if(ql>mid) return ask(tree->rs,mid+1,r,ql,qr);
	return ask(tree->ls,l,mid,ql,qr)+ask(tree->rs,mid+1,r,ql,qr);
}

简单平衡树

std::set

替罪羊树

#define alpha 0.7
struct Node{
	Node *ls,*rs;
	int val,cnt,size;//size:num of not deleted,cnt:all
	int deleted;
	inline void pushup(){}
}*null,*root,*nodes[1100005],**badtag;
int nodeNum;
inline int isbad(Node *tree){return tree->ls->cnt>alpha*tree->cnt+5||tree->rs->cnt>alpha*tree->cnt+5;}
void dfs(Node *tree){
	if(tree==null) return;
	dfs(tree->ls);
	if(!tree->deleted) nodes[++nodeNum]=tree;
	dfs(tree->rs);
	if(tree->deleted) delete tree;
}
Node *build(int l,int r){
	if(l>r) return null;
	if(l==r){
		nodes[l]->ls=nodes[l]->rs=null;
		nodes[l]->cnt=nodes[l]->size=1;
		return nodes[l];
	}
	int mid=(l+r)>>1;
	Node *tree=nodes[mid];
	tree->ls=build(l,mid-1);tree->rs=build(mid+1,r);
	tree->pushup();
	return tree;
}
inline void rebuild(Node *&tree){
	nodeNum=0;
	dfs(tree);
	tree=build(1,nodeNum);
}
void insert(Node *&tree,int x){
	if(tree==null){
		tree=new Node;
		tree->ls=tree->rs=null;
		tree->deleted=0;tree->val=x;
		tree->size=tree->cnt=1;
		return;
	}
	tree->size++;tree->cnt++;
	if(x>tree->val) insert(tree->rs,x);
	else insert(tree->ls,x);
	if(isbad(tree)) badtag=&tree;
}
inline void Insert(Node *&tree,int x){
	badtag=&null;
	insert(tree,x);
	if(badtag!=&null) rebuild(*badtag);
}
inline int rank(Node *tree,int x){
	int ans=1;
	while(tree!=null){
		if(x<=tree->val) tree=tree->ls;
		else{
			ans+=tree->ls->size+!tree->deleted;
			tree=tree->rs;
		}
	}
	return ans;
}
inline int kth(tr *tree,int rk){
	while(tree!=null){
		if(!tree->deleted&&tree->ls->size+1==rk) return tree->val;
		if(rk<=tree->ls->size) tree=tree->ls;
		else{
			rk-=tree->ls->size+!tree->deleted;
			tree=tree->rs;
		}
	}
}
void erase(tr *tree,int rk){
	if(!tree->deleted&&rk==tree->ls->size+1){
		tree->deleted=1;
		tree->size--;
		return;
	}
	tree->size--;
	if(rk<=tree->ls->size+!tree->deleted) erase(tree->ls,rk);
	else erase(tree->rs,rk-tree->ls->size-!tree->deleted);
}

fhq-treap

struct Node{
	Node *ls,*rs;
	int val,rnd,size;
	inline void pushup(){size=1+ls->size+rs->size;}
}*root,*null;
inline void init(Node *x){x->ls=x->rs=null;x->size=1;x->rnd=rand();}
inline void init(){
	srand(822);
	null=new Node;null->ls=null->rs=null;null->size=0;null->val=INT_INF;
	root=null;
}
void split(Node *tree,int k,Node *&L,Node *&R){
	if(tree==null) return L=R=null,void();
	if(tree->ls->size>=k){
		R=tree;
		split(tree->ls,k,L,R->ls);
		R->pushup();
	}
	else{
		L=tree;
		split(tree->rs,k-tree->ls->size-1,L->rs,R);
		L->pushup();
	}
}
Node* merge(Node *L,Node *R){
	if(L==null) return R;
	if(R==null) return L;
	if(L->rnd<R->rnd){
		L->rs=merge(L->rs,R);
		return L->pushup(),L;
	}
	else{
		R->ls=merge(L,R->ls);
		return R->pushup(),R;
	}
}
inline int rank(int val){
	int ans=1;
	Node *tree=root;
	while(tree!=null){
		if(val<=tree->val) tree=tree->ls;
		else{
			ans+=tree->ls->size+1;
			tree=tree->rs;
		}
	}
	return ans;
}
inline void insert(int val){
	int rk=rank(val)-1;
	Node *x,*y;
	split(root,rk,x,y);
	Node *a=new Node;init(a);a->val=val;
	root=merge(merge(x,a),y);
}
inline void del(int val){
	int rk=rank(val);
	Node *x,*y,*z;
	split(root,rk,x,z);
	split(x,rk-1,x,y);//y->val=val,y->size=1
	root=merge(x,z);
	delete y;
}
inline int kth(int k){
	Node *x,*y,*z;
	split(root,k-1,x,y);
	split(y,1,y,z);
	root=merge(x,merge(y,z));
	return y->val;
}

link-cut-tree

struct LCT{
	struct Node{
		Node *son[2],*fa;
		int val,res;
		int tag;
	}dizhi[N],*null;
	inline void init(){null=&dizhi[0];}
	#define ident(tree,fa) (fa->son[1]==tree)
	#define notroot(tree) (tree->fa->son[0]==tree||tree->fa->son[1]==tree)
	#define pushup(tree) (tree->res=tree->son[0]->res^tree->son[1]->res^tree->val)
	inline void connect(Node *tree,Node *fa,int k){fa->son[k]=tree;tree->fa=fa;}
	inline void pushdown(Node *tree){
		if(!tree->tag) return;
		tree->tag=0;
		tree->son[0]->tag^=1;tree->son[1]->tag^=1;
		std::swap(tree->son[0],tree->son[1]);
	}
	inline void rotate(Node *tree){
		Node *fa=tree->fa,*faa=fa->fa;
		pushdown(fa);pushdown(tree);
		int k=ident(tree,fa);
		connect(tree->son[k^1],fa,k);
		tree->fa=faa;
		if(notroot(fa)) faa->son[ident(fa,faa)]=tree;
		connect(fa,tree,k^1);
		pushup(fa);pushup(tree);
	}
	inline void splay(Node *tree){
		Node *fa=tree->fa,*faa=fa->fa;
		while(notroot(tree)){
			fa=tree->fa;faa=fa->fa;
			if(notroot(fa)) rotate((ident(tree,fa)^ident(fa,faa))?tree:fa);
			rotate(tree);
		}
	}
	inline void access(Node *x){
		for(Node *lastx=null;x!=null;lastx=x,x=x->fa){
			pushdown(x);splay(x);x->son[1]=lastx;pushup(x);
		}
	}
	inline void makeroot(Node *x){access(x);splay(x);x->tag^=1;}
	inline Node* findroot(Node *x){
		access(x);splay(x);pushdown(x);
		while(x->son[0]!=null) x=x->son[0],pushdown(x);
		splay(x);return x;
	}
	inline void link(Node *x,Node *y){makeroot(x);if(findroot(y)!=x) x->fa=y;}
	inline void cut(Node *x,Node *y){
		makeroot(x);
		if(findroot(y)!=x||y->fa!=x||y->son[0]!=null) return;
		y->fa=x->son[1]=null;pushup(x);
	}
	inline Node* split(Node *x,Node *y){makeroot(x);access(y);splay(y);return y;}
	inline Node* Split(int x,int y){return split(&dizhi[x],&dizhi[y]);}
	inline void Link(int x,int y){link(&dizhi[x],&dizhi[y]);}
	inline void Cut(int x,int y){cut(&dizhi[x],&dizhi[y]);}
	inline void Change(int o,int val){Node *x=&dizhi[o];splay(x);x->val=val;pushup(x);}
};

数学

lu div

inline void luDiv(int n,ModInt (*l)[N],ModInt (*u)[N],ModInt (*a)[N]){
	for(int i=1;i<=n;i++){
		for(int j=i;j<=n;j++){
			u[i][j]=a[i][j];
			for(int k=1;k<i;k++) u[i][j]-=l[i][k]*u[k][j];
			l[j][i]=a[j][i];
			for(int k=1;k<i;k++) l[j][i]-=l[j][k]*u[k][i];
			l[j][i]/=u[i][i];
		}
		l[i][i]=1;
	}
}

其他

快速幂

inline long long power(long long a,long long b,long long mod=MOD){
	long long ans=1;
	while(b){if(b&1) ans=ans*a%mod;a=a*a%mod;b>>=1;}
	return ans;
}

取模

inline long long power(long long a,long long b,long long mod=MOD){
	long long ans=1;
	while(b){if(b&1) ans=ans*a%mod;a=a*a%mod;b>>=1;}
	return ans;
}
struct ModInt{
	long long x;
#define inline __attribute__((always_inline))
	inline ModInt operator - (ModInt o){return {(x-o.x<0)?(x-o.x+MOD):(x-o.x)};}
	inline ModInt operator - (int o){return {(x-o<0)?(x-o+MOD):(x-o)};}
	inline void operator -= (ModInt o){x=(x-o.x<0)?(x-o.x+MOD):(x-o.x);}
	inline void operator -= (int o){x=(x-o<0)?(x-o+MOD):(x-o);}
	inline friend ModInt operator - (int a,ModInt b){return {(a-b.x<0)?(a-b.x+MOD):(a-b.x)};}
	inline void operator -- (int){x--;if(x<0) x=MOD-1;}
	inline ModInt operator + (ModInt o){return {(x+o.x>=MOD)?(x+o.x-MOD):(x+o.x)};}
	inline ModInt operator + (int o){return {(x+o>=MOD)?(x+o-MOD):(x+o)};}
	inline void operator += (ModInt o){x=(x+o.x>=MOD)?(x+o.x-MOD):(x+o.x);}
	inline void operator += (int o){x=(x+o>=MOD)?(x+o-MOD):(x+o);}
	inline friend ModInt operator + (int a,ModInt b){return {(b.x+a>=MOD)?(b.x+a-MOD):(b.x+a)};}
	inline void operator ++ (int){x++;if(x==MOD) x=0;}
	inline ModInt operator * (ModInt o){return {x*o.x%MOD};}
	inline ModInt operator * (int o){return {x*o%MOD};}
	inline void operator *= (ModInt o){x=x*o.x%MOD;}
	inline void operator *= (int o){x=x*o%MOD;}
	inline friend ModInt operator * (int a,ModInt b){return {a*b.x%MOD};}
	inline ModInt operator / (ModInt o){return {x*power(o.x,MOD-2)%MOD};}
	inline ModInt operator / (int o){return {x*power(o,MOD-2)%MOD};}
	inline void operator /= (ModInt o){x=x*power(o.x,MOD-2)%MOD;}
	inline void operator /= (int o){x=x*power(o,MOD-2)%MOD;}
	inline friend ModInt operator / (int a,ModInt b){return {a*power(b.x,MOD-2)%MOD};}
	inline void operator = (int a){x=a;}
	inline int operator == (const ModInt &o){return x==o.x;}
	inline int operator == (const int &o){return x==o;}
#undef inline
};

fread 和 fwrite

namespace FastIO{
	#define BUF_SIZE 33554432
	char buff[BUF_SIZE];char *p1=buff,*p2=buff;
	#define getChar (p1==p2&&(p2=(p1=buff)+fread(buff,1,BUF_SIZE,stdin),p1==p2)?EOF:*p1++)
	__attribute__((always_inline))inline int read(){
		register int x=0;register char c=getChar;
		while(c<'0'||c>'9')	c=getChar;while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getChar;return x;
	}
	__attribute__((always_inline))inline int reads(){
		register int x=0,y=1;register char c=getChar;
		while(c<'0'||c>'9') y&=(c!='-'),c=getChar;while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getChar;return y?x:-x;
	}
	__attribute__((always_inline))inline long long readl(){
		register long long x=0;register char c=getChar;
		while(c<'0'||c>'9') c=getChar;while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getChar;return x;
	}
	__attribute__((always_inline))inline int readsl(){
		register long long x=0;register int y=1;register char c=getChar;
		while(c<'0'||c>'9') y&=(c!='-'),c=getChar;while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getChar;return y?x:-x;
	}
	__attribute__((always_inline))inline void read(char *s){
		register char c=getChar;while(c=='
'||c=='
'||c==' '||c=='	') c=getChar;
        while(c!='
'&&c!='
'&&c!=' '&&c!='	'&&c!=EOF) *s=c,s++,c=getChar;*s=0;
	}
	#undef getChar
	#define EN write('
')
	#define SPACE write(' ')
	char buffW[BUF_SIZE];int bb;
	char stack[28];
	__attribute__((always_inline))inline void write(register int x,register short base=10){
		if(!x) return buffW[bb++]='0',void();if(x<0) buffW[bb++]='-',x=-x;
		register short top=0;
		while(x) stack[++top]=(x%base)^48,x/=base;while(top) buffW[bb++]=stack[top--];
	}
	__attribute__((always_inline))inline void writeEN(register int x,register short base=10){
		if(!x) return buffW[bb++]='0',buffW[bb++]='
',void();if(x<0) buffW[bb++]='-',x=-x;
		register short top=0;
		while(x) stack[++top]=(x%base)^48,x/=base;while(top) buffW[bb++]=stack[top--];buffW[bb++]='
';
	}
	__attribute__((always_inline))inline void writeSP(register int x,register short base=10){
		if(!x) return buffW[bb++]='0',buffW[bb++]=' ',void();if(x<0) buffW[bb++]='-',x=-x;
		register short top=0;
		while(x) stack[++top]=(x%base)^48,x/=base;while(top) buffW[bb++]=stack[top--];buffW[bb++]=' ';
	}
	__attribute__((always_inline))inline void write(register long long x,register short base=10){
		if(!x) return buffW[bb++]='0',void();if(x<0) buffW[bb++]='-',x=-x;
		register short top=0;
		while(x) stack[++top]=(x%base)^48,x/=base;while(top) buffW[bb++]=stack[top--];
	}
	__attribute__((always_inline))inline void writeEN(register long long x,register short base=10){
		if(!x) return buffW[bb++]='0',buffW[bb++]='
',void();if(x<0) buffW[bb++]='-',x=-x;
		register short top=0;
		while(x) stack[++top]=(x%base)^48,x/=base;while(top) buffW[bb++]=stack[top--];buffW[bb++]='
';
	}
	__attribute__((always_inline))inline void writeSP(register long long x,register short base=10){
		if(!x) return buffW[bb++]='0',buffW[bb++]=' ',void();if(x<0) buffW[bb++]='-',x=-x;
		register short top=0;
		while(x) stack[++top]=(x%base)^48,x/=base;while(top) buffW[bb++]=stack[top--];buffW[bb++]=' ';
	}
	__attribute__((always_inline))inline void write(register char c){buffW[bb++]=c;}
	__attribute__((always_inline))inline void write(char *c){while(*c) buffW[bb++]=*c,c++;}
	#define SUC_RETURN fwrite(buffW,1,bb,stdout),0
	#undef BUF_SIZE
}//namespace FastIO

快速排序

使用 sort

计算几何

lib

struct Vector{
	double x,y;
	inline double len(){return std::sqrt(x*x+y*y);}
	inline void operator += (const Vector &a){x+=a.x;y+=a.y;}
	inline void operator -= (const Vector &a){x-=a.x;y-=a.y;}
	inline void operator *= (const double &a){x*=a;y*=a;}
	inline void operator /= (const double &a){x/=a;y/=a;}
	inline Vector operator + (const Vector &a)const{return {x+a.x,y+a.y};}
	inline Vector operator - (const Vector &a)const{return {x-a.x,y-a.y};}
	inline Vector operator * (const double &a)const{return {x*a,y*a};}
	inline Vector operator / (const double &a)const{return {x/a,y/a};}
	inline double operator * (const Vector &a)const{return x*a.x+y*a.y;}
	inline double operator ^ (const Vector &a)const{return x*a.y-y*a.x;}
};
struct Line{
	Vector p,way;
	double ang;
	inline void makeLine(const Vector &a,const Vector &b){p=a;way=b;ang=atan2(b.y,b.x);}
};
inline int onRight(const Line &a,const Vector &b){return (a.way^(b-a.p))<=-eps;}
inline Vector intersect(const Line &a,const Line &b){
	double x=(b.way^(a.p-b.p))/(a.way^b.way);
	return a.p+a.way*x;
}
inline double polygonArea(int n,Vector *a){
	double S=0;
	for(int i=1;i<n;i++) S+=(a[i]^a[i+1]);
	S+=(a[n]^a[1]);
	return S/2;
}

二维凸包

inline int graham(int n,Vector *p,Vector *stack){
	for(int i=2;i<=n;i++) p[i].ang=atan2(p[i].y-p[1].y,p[i].x-p[1].x);
	std::sort(p+2,p+1+n);
	stack[1]=p[1];int top=1;
	for(int i=2;i<=n;i++){
		while(top>1&&cross(p[i]-stack[top],stack[top]-stack[top-1])<=eps) top--;
		stack[++top]=p[i];
	}
	stack[++top]=p[1];
	return top;
}

半平面交

int left,right;
Line que[N];
inline int halfPlane(int n,Line *a,Vector *p){
	std::sort(a+1,a+1+n,cmp);
	left=right=0;que[0]=a[1];
	for(int i=2;i<=n;i++){
		while(left<right&&onRight(a[i],p[right])) right--;
		while(left<right&&onRight(a[i],p[left+1])) left++;
		que[++right]=a[i];
		if(abs(cross(que[right].way,que[right-1].way))<=eps){//平行
			if(onRight(que[right],que[right-1].p)&&abs(que[right].way.y+que[right-1].way.y+que[right].way.x+que[right-1].way.x)<=eps) return 0;
			right--;
			if(!onRight(que[right],a[i].p)) que[right]=a[i];
		}
		if(left<right) p[right]=intersect(que[right],que[right-1]);
	}
	while(left<right&&onRight(que[left],p[right])) right--;
	if(right-left<=1) return 0;
	p[left]=intersect(que[left],que[right]);
	return 1;
}

旋转卡壳

inline int nex(int i){return i==n?1:(i+1);}
int main(){
	if(n<=3) return printf("%lld
",(q[2]-q[1]).len()),0;
	long long ans=0;
	for(int i=1,j=3;i<n;i++){
		while(abs((q[j]-q[i])^(q[j]-q[i+1]))<=abs((q[nex(j)]-q[i])^(q[nex(j)]-q[i+1]))) j=nex(j);
		ans=std::max(ans,std::max((q[j]-q[i]).len(),(q[j]-q[i+1]).len()));
	}
	printf("%lld
",ans);
	return 0;
}

字符串

kmp

manacher

AC 自动机

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

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;
}

PAM

struct Node{
	Node *son[26],*fail;
	int len,cnt;
}dizhi[N],*root0=&dizhi[0],*root1=&dizhi[1],*last;
int tot;
inline void init(){
	last=root1;
	root0->fail=root1;root1->fail=root0;
	root1->len=-1;
	tot=1;
}
char s[N];
inline int cnt(Node *u){
	if(u==root0||u==root1) return 0;
	if(u->cnt) return u->cnt;
	return u->cnt=1+cnt(u->fail);
}
inline int insert(int i){
	while(s[i-last->len-1]^s[i]) last=last->fail;
	if(!last->son[s[i]-'a']){
		Node *u=&dizhi[++tot];
		u->len=last->len+2;
		reg Node *j=last->fail;
		while(s[i-j->len-1]^s[i]) j=j->fail;
		u->fail=j->son[s[i]-'a'];
		if(!u->fail) u->fail=root0;
		last->son[s[i]-'a']=u;
	}
	last=last->son[s[i]-'a'];
	return cnt(last);
}
原文地址:https://www.cnblogs.com/suxxsfe/p/15463439.html