模板

SA

int sa[N],rk[N],oldrk[N<<1],id[N],cnt[N];
void calcSA(int n,int V){
    int pos=0;
    forUp(i,1,n)++cnt[rk[i]=s[i]];
	forUp(i,1,V)cnt[i]+=cnt[i-1];
	forDown(i,n,1)sa[cnt[rk[i]]--]=i;
	for(int j=1;;j<<=1,V=pos){
		int cur=0;
		forUp(i,n-j+1,n)id[++cur]=i;
		forUp(i,1,n)if(sa[i]>j)id[++cur]=sa[i]-j;
		memset(cnt,0,sizeof(cnt));
		forUp(i,1,n)++cnt[rk[i]];
		forUp(i,1,V)cnt[i]+=cnt[i-1];
		forDown(i,n,1)sa[cnt[rk[id[i]]]--]=id[i];
		memcpy(oldrk,rk,sizeof(rk));
		pos=0;
		forUp(i,1,n){
			if(oldrk[sa[i]]==oldrk[sa[i-1]]&&oldrk[sa[i]+j]==oldrk[sa[i-1]+j])rk[sa[i]]=pos;
			else rk[sa[i]]=++pos;
		}
		if(pos==n)break;
	}
}

Miller-Rabin

ll QuickPow(ll x,ll y,ll mod){
	ll ans=1ll;
	while(y){
		if(y&1ll)ans=ans*x%mod;
		x=x*x%mod;
		y>>=1ll;
	}
	return ans;
}

bool MillerRabin(ll n){
	if(n<3ll||!(n&1))return n==2;
	if(n%3==0)return n==3;
	const int test_time=7;
	const ll a[7]={2ll,325ll,9375ll,28178ll,450775ll,9780504ll,1795265022ll};
	ll p=n-1ll,q=0ll;
	while(!(p&1))p>>=1,++q;
	for(int i=0;i<test_time;++i){
		if(a[i]%n==0ll||a[i]%n==1ll||a[i]%n==n-1ll)continue;
		ll ans=QuickPow(a[i]%n,p,n);
		if(ans==1ll)continue;
		int j;
		for(j=0;j<q;++j){
			if(ans==n-1ll)break;
			ans=ans*ans%n;
		}
		if(j==q)return false;
	}
	return true;
}

NTT

constexpr ull mod=998244353,G=3,invG=332748118;int rev[LIM];
ull qp(ull x,ull y){ull ans=1;for(;y;y>>=1,x=x*x%mod)if(y&1)ans=ans*x%mod;return ans;}
ull F[LIM],prod[LIM]={1},tmp;
void NTT(int lim,int *f,bool opt){
	static bool first=true;
	if(first){
		first=false;
		forUP(i,1,lim)rev[i]=(rev[i>>1]>>1)|(i&1?lim>>1:0);
	}
	forUP(i,0,lim)F[i]=f[rev[i]];
	for(int k=1;k<lim;k<<=1){
		ull tG=qp(opt?invG:G,(mod-1)/(k<<1));
		forUP(i,1,k)prod[i]=prod[i-1]*tG%mod;
		for(int i=0;i<lim;i+=k<<1){
			for(int j=0;j<k;++j){
				tmp=prod[j]*F[i|j|k]%mod;
				F[i|j|k]=F[i|j]+mod-tmp;
				F[i|j]+=tmp;
			}
		}
		if(k==(1<<17))forUP(i,0,lim)F[i]%=mod;
	}
	if(opt){
		ull INV=qp(lim,mod-2);
		forUP(i,0,lim)f[i]=F[i]*INV%mod;
	}
	else forUP(i,0,lim)f[i]=F[i]%mod;
}

FWT

enum{OR,AND,XOR};
void FWT(int n,ll *arr,int type,bool inv){
	switch(type){
		case OR:
		for(int len=2;len<=n;len<<=1){
			int k=len>>1;
			for(int i=0;i<n;i+=len)for(int j=0;j<k;++j)(arr[i+j+k]+=inv?mod-arr[i+j]:arr[i+j])%=mod;
		}break;
		case AND:
		for(int len=2;len<=n;len<<=1){
			int k=len>>1;
			for(int i=0;i<n;i+=len)for(int j=0;j<k;++j)(arr[i+j]+=inv?mod-arr[i+j+k]:arr[i+j+k])%=mod;
		}break;
		case XOR:
		for(int len=2;len<=n;len<<=1){
			int k=len>>1;
			for(int i=0;i<n;i+=len)for(int j=0;j<k;++j){
				(arr[i+j]+=arr[i+j+k])%=mod;
				(arr[i+j+k]=(arr[i+j]-(arr[i+j+k]<<1))%mod)<0?arr[i+j+k]+=mod:0;
				(arr[i+j]*=inv?inv2:1)%=mod;
				(arr[i+j+k]*=inv?inv2:1)%=mod;
			}
		}break;
	}
}

Link-Cut Tree

int fa[N],son[N][2];bool rev[N];
bool nroot(int node){return son[fa[node]][0]==node||son[fa[node]][1]==node;}
void pushup(int node){
	//pushup
}
void modifyRev(int node){
	rev[node]^=1;
    swap(son[node][0],son[node][1]);
}
void pushdown(int node){
	if(rev[node]){
		if(son[node][0])modifyRev(son[node][0]);
		if(son[node][1])modifyRev(son[node][1]);
		rev[node]=0;
	}
	//other modify
}
void rotate(int node){
	int father=fa[node],grand=fa[father],dir=son[father][1]==node,tmp=son[node][!dir];
	if(nroot(father))son[grand][son[grand][1]==father]=node;
	son[node][!dir]=father,son[father][dir]=tmp;
	if(tmp)fa[tmp]=father;
	fa[father]=node,fa[node]=grand;
	pushup(father);pushup(node);
}
void clearTag(int node){
	if(nroot(node))clearTag(fa[node]);
	pushdown(node);
}
void splay(int node){
	clearTag(node);
	while(nroot(node)){
		int father=fa[node],grand=fa[father];
		if(nroot(father))rotate((son[father][0]==node)^(son[grand][0]==father)?node:father);
		rotate(node);
	}
	pushup(node);
}
int access(int node){
	int tmp=0;
	for(;node;node=fa[tmp=node])splay(node),son[node][1]=tmp,pushup(node);
	return tmp;
}
void makeRoot(int node){
	access(node);splay(node);
	modifyRev(node);
}
int findRoot(int node){
	access(node);splay(node);
	while(son[node][0])pushdown(node),node=son[node][0];
	splay(node);
	return node;
}
void split(int node1,int node2){
	makeRoot(node1);
	access(node2);splay(node2);
}
void link(int node1,int node2){
	makeRoot(node1);
	if(findRoot(node2)!=node1)makeRoot(node2),fa[node1]=node2;
}
void cut(int node1,int node2){
	makeRoot(node1);
	if(findRoot(node2)==node1&&fa[node2]==node1&&!son[node2][0]){
		fa[node2]=son[node1][1]=0;
		pushup(node1);
	}
}

Dinic

struct edge{int to,nxt,cap,flow;}e[M];int cnt,head[N];

int dep[N],cur[N];ll maxflow;
void init(){maxflow=cnt=0;memset(head,-1,sizeof(head));}
void addEdge(int u,int v,int c){
	e[cnt]=(edge){v,head[u],c,0};head[u]=cnt++;
	e[cnt]=(edge){u,head[v],0,0};head[v]=cnt++;
}

bool bfs(int S,int T){
	queue<int> q;
    memset(dep,0,sizeof(dep));
    memcpy(cur,head,sizeof(cur));
	dep[S]=1;q.push(S);
	while(!q.empty()){
		int u=q.front();q.pop();
		for(int i=head[u];~i;i=e[i].nxt){
			int v=e[i].to;
			if(!dep[v]&&e[i].cap>e[i].flow){
				dep[v]=dep[u]+1;
				q.push(v);
			}
		}
	}
	return dep[T];
}
int dfs(int T,int u,int flow){
	if(u==T||!flow)return flow;
	int ans=0;
	for(int &i=cur[u];~i;i=e[i].nxt){
		int v=e[i].to,delta;
		if(dep[v]==dep[u]+1&&(delta=dfs(T,v,min(flow-ans,e[i].cap-e[i].flow)))){
			ans+=delta;
			e[i].flow+=delta;
			e[i^1].flow-=delta;
			if(ans==flow)break;
		}
	}
	return ans;
}
void dinic(int S,int T){
	while(bfs(S,T))maxflow+=dfs(T,S,INF);
}

SSP

struct edge{int to,nxt,cap,cost,flow;}e[M];int cnt,head[N];

int cur[N];ll dis[N],maxflow,mincost;bool vis[N];
void init(){cnt=maxflow=mincost=0;memset(head,-1,sizeof(head));}
void addEdge(int u,int v,int cap,int cost){
	e[cnt]={v,head[u],cap,cost,0};head[u]=cnt++;
	e[cnt]={u,head[v],0,-cost,0};head[v]=cnt++;
}
bool SPFA(int S,int T,bool flag){
	queue<int> q;
	if(flag)memset(dis,0x3f,sizeof(dis));
	else memset(dis,0xcf,sizeof(dis));
	memcpy(cur,head,sizeof(cur));
	q.push(S),dis[S]=0,vis[S]=true;
	while(!q.empty()){
		int u=q.front();q.pop();
		vis[u]=false;
		for(int i=head[u];~i;i=e[i].nxt){
			int v=e[i].to;
			if(((flag&&dis[v]>dis[u]+e[i].cost)||(!flag&&dis[v]<dis[u]+e[i].cost))&&e[i].cap>e[i].flow){
				dis[v]=dis[u]+e[i].cost;
				if(!vis[v]){
					q.push(v);
					vis[v]=true;
				}
			}
		}
	}
	return flag?dis[T]!=INFLL:dis[T]!=MINFLL;
}
int dfs(int T,int u,int flow){
	if(u==T||!flow)return flow;
	int ans=0;
	vis[u]=true;
	for(int &i=cur[u];~i;i=e[i].nxt){
		int v=e[i].to,delta;
		if(!vis[v]&&dis[v]==dis[u]+e[i].cost&&(delta=dfs(T,v,min(flow-ans,e[i].cap-e[i].flow)))){
			ans+=delta;
			e[i].flow+=delta;
			e[i^1].flow-=delta;
			mincost+=delta*e[i].cost;
			if(ans==flow)break;
		}
	}
	vis[u]=false;
	return ans;
}
void SSP(int S,int T,bool flag=true){
	int flow;
	while(SPFA(S,T,flag))while((flow=dfs(T,S,INF)))maxflow+=flow;
}

fastIO

namespace LXcjh4998{
namespace internal{namespace type_traits{
    template<class _Tp>using __is_signed_int128=typename std::conditional<std::is_same<_Tp,__int128_t>::value||std::is_same<_Tp,__int128>::value,std::true_type,std::false_type>::type;
	template<class _Tp>using __is_unsigned_int128=typename std::conditional<std::is_same<_Tp,__uint128_t>::value||std::is_same<_Tp,unsigned __int128>::value,std::true_type,std::false_type>::type;
	template<class _Tp>using __make_unsigned_int128=typename std::conditional<std::is_same<_Tp,__int128_t>::value,__uint128_t,unsigned __int128>;
	template<class _Tp>using __is_integer=typename std::conditional<std::is_integral<_Tp>::value||__is_signed_int128<_Tp>::value||__is_unsigned_int128<_Tp>::value,std::true_type,std::false_type>::type;
	template<class _Tp>using __is_signed_integer=typename std::conditional<(__is_integer<_Tp>::value&&std::is_signed<_Tp>::value)||__is_signed_int128<_Tp>::value,std::true_type,std::false_type>::type;
	template<class _Tp>using __is_unsigned_integer=typename std::conditional<(__is_integer<_Tp>::value&&std::is_unsigned<_Tp>::value)||__is_unsigned_int128<_Tp>::value,std::true_type,std::false_type>::type;
	template<class _Tp>using __to_unsigned=typename std::conditional<__is_signed_int128<_Tp>::value,__make_unsigned_int128<_Tp>,typename std::conditional<std::is_signed<_Tp>::value,std::make_unsigned<_Tp>,std::common_type<_Tp>>::type>::type;
	template<class _Tp>using __is_signed_integer_type=std::enable_if_t<__is_signed_integer<_Tp>::value>;
	template<class _Tp>using __is_unsigned_integer_type=std::enable_if_t<__is_unsigned_integer<_Tp>::value>;
	template<class _Tp>using __to_unsigned_type=typename __to_unsigned<_Tp>::type;
}using namespace type_traits;namespace check_char_type{bool __is_digit(const char &c){return 48<=c&&c<=57;}bool __is_not_blank(const char &c){return c^32&&c^10&&c^13&&c&&~c;}}using namespace check_char_type;}
namespace fastIO{
	struct istream{void tie([[maybe_unused]]int x){}}fin;struct ostream{void tie([[maybe_unused]]int x){}}fout;
	constexpr int __maxn=1<<20;char __in[__maxn],__out[__maxn],*__p1=__in,*__p2=__in,*__p3=__out;
	#define getchar() (__p1==__p2&&(__p2=(__p1=__in)+fread(__in,1,__maxn,stdin),__p1==__p2)?EOF:*__p1++)
	#define flush() (fwrite(__out,1,__p3-__out,stdout))
	#define putchar(ch) (__p3==__out+__maxn&&(flush(),__p3=__out),*__p3++=(ch))
	class __flush{public:~__flush(){flush();}}__var_to_flush;
	template<typename _Tp,internal::__is_signed_integer_type<_Tp>* =nullptr>istream& operator>>(istream &fin,_Tp &x){x=0;bool flag(false);char ch=getchar();while(!internal::__is_digit(ch))flag^=!(ch^45),ch=getchar();while(internal::__is_digit(ch))x=(x<<1)+(x<<3)+(ch^48),ch=getchar();flag?x=-x:x;return fin;}
	template<typename _Tp,internal::__is_unsigned_integer_type<_Tp>* =nullptr>istream& operator>>(istream &fin,_Tp &x){x=0;char ch=getchar();while(!internal::__is_digit(ch))ch=getchar();while(internal::__is_digit(ch))x=(x<<1)+(x<<3)+(ch^48),ch=getchar();return fin;}
	istream& operator>>(istream &fin,char &x){do x=getchar();while(!internal::__is_not_blank(x));return fin;}
	istream& operator>>(istream &fin,char *x){char ch=getchar();do *(x++)=ch;while(internal::__is_not_blank(ch=getchar()));return fin;}
	istream& operator>>(istream &fin,std::string &x){char ch=getchar();x.clear();do x+=ch;while(internal::__is_not_blank(ch=getchar()));return fin;}
	template<typename _Tp,internal::__is_unsigned_integer_type<_Tp>* =nullptr>ostream& operator<<(ostream &fout,_Tp x){int stk[50],tp(0);do stk[++tp]=x%10,x/=10;while(x);while(tp)putchar(stk[tp--]|48);return fout;}
	template<typename _Tp,internal::__is_signed_integer_type<_Tp>* =nullptr>ostream& operator<<(ostream &fout,_Tp x){internal::__to_unsigned_type<_Tp> tmp=x<0?(putchar(45),-x):x;fout<<tmp;return fout;}
	ostream& operator<<(ostream &fout,const char &x){putchar(x);return fout;}
	template<typename _Tp>ostream& operator<<(ostream &fout,_Tp *x){while(*x)putchar(*(x++));return fout;}
	ostream& operator<<(ostream &fout,const std::string &x){for(const char &ch:x)putchar(ch);return fout;}
	#undef getchar
	#undef putchar
	#undef flush
	#define cin LXcjh4998::fin
	#define cout LXcjh4998::fout
}using namespace fastIO;}

DS::Treap

namespace LXcjh4998{namespace DS{namespace Treap{
	template<class _Tp,int (*rand)(void),_Tp min_value,_Tp max_value>
	struct treap{
		private:int tot,rt;std::vector<int> lson,rson,cnt,rnd,sz;std::vector<_Tp> val;
		inline void pushup(int node){sz[node]=sz[lson[node]]+sz[rson[node]]+cnt[node];}
		inline void lrotate(int &node){int tmp=rson[node];rson[node]=lson[tmp];lson[tmp]=node;sz[tmp]=sz[node];pushup(node);node=tmp;}
		inline void rrotate(int &node){int tmp=lson[node];lson[node]=rson[tmp];rson[tmp]=node;sz[tmp]=sz[node];pushup(node);node=tmp;}
		void insert(int &node,const _Tp &value){if(!node){node=++tot;val[node]=value;cnt[node]=sz[node]=1;rnd[node]=rand();return;}++sz[node];if(val[node]==value)++cnt[node];else if(value<val[node]){insert(lson[node],value);if(rnd[lson[node]]<rnd[node])rrotate(node);}else{insert(rson[node],value);if(rnd[rson[node]]<rnd[node])lrotate(node);}}
		bool remove(int &node,const _Tp &value){if(!node)return false;if(val[node]==value){if(cnt[node]>1){--sz[node],--cnt[node];return true;}if(!lson[node]||!rson[node]){node=lson[node]|rson[node];return true;}if(rnd[lson[node]]<rnd[rson[node]])rrotate(node);else lrotate(node);return remove(node,value);}else if(value<val[node]){bool success=remove(lson[node],value);if(success)--sz[node];return success;}else{bool success=remove(rson[node],value);if(success)--sz[node];return success;}}
		public:
		treap():tot(0),rt(0){}
		treap(int n):tot(0),rt(0),lson(n+1),rson(n+1),cnt(n+1),rnd(n+1),sz(n+1),val(n+1){}
		void insert(const _Tp &value){insert(rt,value);}
		bool remove(const _Tp &value){return remove(rt,value);}
		int query_rank(const _Tp &value){int cur=rt,rank=0;for(;cur;){if(val[cur]==value)return rank+sz[lson[cur]]+1;else if(value<val[cur])cur=lson[cur];else rank+=sz[lson[cur]]+cnt[cur],cur=rson[cur];}return rank+1;}
		_Tp query_by_rank(int rank){assert(1<=rank&&rank<=sz[rt]);int cur=rt;for(;rank<=sz[lson[cur]]||sz[lson[cur]]+cnt[cur]<rank;){if(rank<=sz[lson[cur]])cur=lson[cur];else rank-=sz[lson[cur]]+cnt[cur],cur=rson[cur];}return val[cur];}
		_Tp query_prev(const _Tp &value){int cur=rt,res=0;for(;cur;){if(val[cur]<value)res=cur,cur=rson[cur];else cur=lson[cur];}return res?val[res]:min_value;}
		_Tp query_next(const _Tp &value){int cur=rt,res=0;for(;cur;){if(val[cur]>value)res=cur,cur=lson[cur];else cur=rson[cur];}return res?val[res]:max_value;}
	};
}using namespace Treap;}}
posted @ 2025-05-05 19:19  LXcjh4998  阅读(31)  评论(0)    收藏  举报