zoukankan      html  css  js  c++  java
  • 模板库

    缺省源

    #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);
    }
    
  • 相关阅读:
    PHP编译安装
    PHP编译安装
    Apache编译安装
    Apache编译安装
    端口号
    端口号
    初步理解TCP/IP网络
    初步理解TCP/IP网络
    剑指offer——树的子结构
    STL四种智能指针
  • 原文地址:https://www.cnblogs.com/suxxsfe/p/15463439.html
Copyright © 2011-2022 走看看