ACM 各种模板整理

1 篇文章 0 订阅
1 篇文章 0 订阅
这篇博客整理了ACM竞赛中常用的算法模板,包括静态仙人掌、非旋Treap、Tarjan算法、线段树、树状数组及其优化版、ST表、Trie树、Manacher算法以及FFT和矩阵乘法快速幂等。
摘要由CSDN通过智能技术生成

静态仙人掌(圆方树)

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pr std::pair<int,int>
#define mk(a,b) std::make_pair(a,b)
const int maxm=2e5+5;
const int maxn=1e5+5;
struct EDGE{
	int nxt,to;
	LL val;
}e[maxm*4];
int etot=0;
int node[maxn*2];
void add(int x,int y,LL v){
	e[++etot].val=v;
	e[etot].to=y;
	e[etot].nxt=node[x];
	node[x]=etot;
}
vector<int>g;
LL sum_val[maxn*2];
int tot=0,col=0,dfn[maxn],low[maxn],stk[maxn],top=0;
int n,m,max_e;
void tarjan(int x,int fa=0){
	dfn[x]=low[x]=++tot;
	stk[++top]=x;
	for(int i=node[x];i;i=e[i].nxt)if(e[i].to!=fa){
		if(dfn[e[i].to])low[x]=min(low[x],dfn[e[i].to]);
		else{
			tarjan(e[i].to,x);
			low[x]=min(low[x],low[e[i].to]);
			if(low[e[i].to]>=dfn[x]){
				col++;
				g.clear();
				g.push_back(x);
				do g.push_back(stk[top]);
				while(stk[top--]!=e[i].to);
				LL sum=0;
				for(int j=0;j<g.size();j++){
					int now=g[j],too=g[(j+1)%g.size()];
					for(int P=node[too];P;P=e[P].nxt){
						if(e[P].to==now){
							sum+=e[P].val;
							break;
						}
					}
				}
				LL tsum=0;
				for(int j=0;j<g.size();j++){
					int now=g[j],too=g[(j+1)%g.size()];
					for(int P=node[too];P;P=e[P].nxt){
						if(e[P].to==now){
							tsum+=e[P].val;
							if(too!=x)sum_val[too]=tsum;
							add(col+n,too,min(tsum,sum-tsum));
							add(too,col+n,min(tsum,sum-tsum));
							break;
						}
					}
				}
				sum_val[col+n]=sum;
			}
		}
	}
}
int dp[maxn*2][19];
LL deep[maxn*2];
int d[maxn*2];
void dfs(int x,int fa){
	d[x]=d[fa]+1;
	dp[x][0]=fa;
	for(int i=node[x];i;i=e[i].nxt)if(i>max_e&&e[i].to!=fa){
		deep[e[i].to]=deep[x]+e[i].val;
		dfs(e[i].to,x);
	}
}
pr LCA(int x,int y){
	for(int i=18;i>=0;i--)if(d[dp[x][i]]>=d[y])x=dp[x][i];
	if(x==y)return mk(x,0);
	for(int i=18;i>=0;i--)if(dp[x][i]!=dp[y][i])x=dp[x][i],y=dp[y][i];
	return mk(x,y);
}
LL ABS(LL v){
	return v<0? -v:v;
}
LL solve(int x,int y){
	if(d[x]<d[y])swap(x,y);
	pr lca=LCA(x,y);
	if(lca.second==0){
		return ABS(deep[x]-deep[y]);
	}
	else{
		if(dp[lca.first][0]<=n)return deep[x]+deep[y]-deep[dp[lca.first][0]]*2;
		else{
			LL tpv=deep[x]+deep[y]-deep[lca.first]-deep[lca.second];
			LL tp=ABS(sum_val[lca.first]-sum_val[lca.second]);
			return tpv+min(tp,sum_val[dp[lca.first][0]]-tp);
		}
	} 
}
int main(){
	int q;
	scanf("%d%d%d",&n,&m,&q);
	for(int i=1;i<=m;i++){
		int l,r,v;
		scanf("%d%d%d",&l,&r,&v);
		add(l,r,v);
		add(r,l,v);
	}
	max_e=etot;
	tarjan(1);
	dfs(1,0);
	for(int k=1;k<19;k++)
	for(int x=col+n;x>=1;x--){
		dp[x][k]=dp[dp[x][k-1]][k-1];
	}
	while(q--){
		int l,r;
		scanf("%d%d",&l,&r);
		printf("%lld\n",solve(l,r));
	}
	return 0; 
}

非旋treap(未封装)

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pr std::pair<int,int>
#define mk(a,b) std::make_pair(a,b)
const int maxn=1e5+5;
struct node{
	int siz,v,son[2],col,wt;
}T[maxn];
#define ls T[x].son[0]
#define rs T[x].son[1]
void updata(int x){
	T[x].siz=1+T[ls].siz+T[rs].siz;
}
void color(int x){
	T[x].col^=1;
	swap(ls,rs);
}
void push_col(int x){
	if(T[x].col){
		color(ls);
		color(rs);
		T[x].col=0;
	}
}
int merge(int x,int y){
	if(x*y==0)return x+y;
	push_col(x);
	push_col(y);	 
	if(T[x].wt>T[y].wt){
		T[x].son[1]=merge(T[x].son[1],y);
		updata(x);
		return x;	
	}else {
		T[y].son[0]=merge(x,T[y].son[0]);
		updata(y);
		return y;	
	}
} 
pr split_rk(int x,int kth){
	if(kth*x==0)return mk(0,x);
	push_col(x);
	if(kth<=T[ls].siz){
		pr tp=split_rk(ls,kth);
		ls=tp.second;
		updata(x);
		return mk(tp.first,x);
	}else{
		pr tp=split_rk(rs,kth-T[ls].siz-1);
		rs=tp.first;
		updata(x);
		return mk(x,tp.second);
	}
}
int tot=0;
int build(int l,int r,int *a){
	if(l>r)return 0;
	int mid=(l+r)>>1;
	int x=++tot;
	T[x].v=a[mid];
	T[x].siz=1;
	T[x].wt=rand();
	if(l==r)return x;
	ls=build(l,mid-1,a);
	rs=build(mid+1,r,a);
	updata(x);
	return x;
}
int root=0;
void reverse(int l,int r){
	pr tp=split_rk(root,l-1);
	pr tpv=split_rk(tp.second,r-l+1);
	color(tpv.first);
	root=merge(merge(tp.first,tpv.first),tpv.second);
}
void dfs(int x){ 
	push_col(x);
	if(!x)return;
	dfs(ls);
	printf("%d ",T[x].v);
	dfs(rs);
}
int n,m,a[maxn];
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)a[i]=i;
	root=build(1,n,a);
	while(m--){
		int l,r;
		scanf("%d%d",&l,&r);
		reverse(l,r);
	}
	dfs(root);
}

tarjan

namespace trj{
	const int maxn=1e5+5;
	const int maxm=2e5+5;
	struct EDGE{
		EDGE *next;
		int to,val;
	}e[maxm*4];
	int etot=0;
	EDGE *node[maxn*2];
	int	nv[maxn*2];
	void add(int x,int y,int val){
		e[++etot].next=node[x];
		node[x]=e+etot;
		e[etot].to=y;
		e[etot].val=val;
	}
	void clear(){
		memset(node,0,sizeof(node));
		memset(nv,0,sizeof(nv));
		etot=0;
	}
	bool use[maxn];
	int dfn[maxn],low[maxn],col[maxn],stk[maxn],top,tot,colnum;
	void dfs(int x,int fa){
		low[x]=dfn[x]=++tot;
		use[x]=true;
		stk[++top]=x;
		for(EDGE *i=node[x];i;i=i->next)if(i->to!=fa){
			if(!dfn[i->to]){
				dfs(i->to,x);
				low[x]=std::min(low[x],low[i->to]);
			}else if(use[i->to])low[x]=std::min(low[x],dfn[i->to]);
		}else fa=0;
		if(dfn[x]==low[x]){
			col[x]=++colnum;
			use[x]=false;
			while(stk[top]!=x){
				use[stk[top]]=false;
				col[stk[top]]=colnum;
				top--;
			}
			top--;
		}
	}
	void tarjan(int n){
		memset(dfn,0,sizeof(dfn));
		tot=0;
		colnum=n;
		for(int i=1;i<=n;i++)if(!dfn[i])dfs(i,0);
		for(int x=1;x<=n;x++){
			nv[col[x]]+=nv[x];
			for(EDGE *i=node[x];i;i=i->next)
			if(col[x]!=col[i->to])add(col[x],col[i->to],i->val);
		} 
	}
}

线段树(区间求和区间加为例)

template<typename tp,typename tpc=tp>
class segment_tree{
	#define lson l,mid,rt<<1 //简化操作 
	#define rson mid+1,r,rt<<1|1
	private:
	int maxn_seg; //设置线段树长度 
	tp *sum; //线段树节点所存权值的和 
	tpc *col; //线段树标记 	

	void updata(int l,int r,int rt){ //更新当前节点的值(自下向上) 
		sum[rt]=(sum[rt<<1]+sum[rt<<1|1]);
	}
	void clear(tpc &x){ //清空节点标记 
		x=0;
	}	
	void color(int l,int r,int rt,tpc colv){ //标记节点 
		col[rt]+=colv;
		sum[rt]+=(r-l+1)*colv;
	}
    void pushcol(int l,int r,int rt){ //下放当前节点的标记 
	    int mid=(l+r)>>1;
    	if(col[rt]){
			color(lson,col[rt]);
			color(rson,col[rt]);
		}
		clear(col[rt]); //下放后清除标记 
	}
	
	public:
	segment_tree(int N){ //初始化线段树长度 
		maxn_seg=N+1;
		sum=new tp[maxn_seg<<2];
		col=new tpc[maxn_seg<<2];
	}
	~segment_tree(){
		delete[]sum;
		delete[]col;
	}
	void build(int l,int r,int rt,tp *orv){ //初始化线段树 
		clear(col[rt]); //初始化标记 
  	  	if(l==r){
			sum[rt]=orv[l]; //初始化权值 
        	return;
		}
    	int mid=(l+r)>>1;
    	build(lson,orv);
   	 	build(rson,orv);
    	updata(l,r,rt); 
	}
	void modify(int l,int r,int rt,int tl,int tr,tpc colv){ //区间[tl,tr]进行colv类型的修改 
   		if(tl<=l&&tr>=r){
        	color(l,r,rt,colv);
        	return;
    	}
    	pushcol(l,r,rt); 
    	int mid=(l+r)>>1;
    	if(tl<=mid)modify(lson,tl,tr,colv);
    	if(tr>mid)modify(rson,tl,tr,colv);
    	updata(l,r,rt);
	}
	tp query(int l,int r,int rt,int tl,int tr){ //对区间[tl,tr]进行查询 
    	if(tl<=l&&tr>=r)return sum[rt];
    	pushcol(l,r,rt);
    	int mid=(l+r)>>1;
    	if(tl<=mid&&tr>mid)return query(lson,tl,tr)+query(rson,tl,tr);
    	else if(tl<=mid)return query(lson,tl,tr);
		else return query(rson,tl,tr);
	}
	#undef lson
	#undef rson
};

树状数组优化版(区间操作和修改)

template<typename tp>
class bit_pro{
	#define lowbit(a) (a&(-a))  //lowbit函数
	private:
	int maxn_bit; //树状数组长度
	tp *val1,*val2; //同时处理两组数以进行区间操作
	
	void add(tp *val,int pos,tp v){ //更改单一数组前缀和
    	for(int i=pos;i<=maxn_bit;i+=lowbit(i))val[i]+=v; 
	}
	tp get(tp *val,int pos){ //求到单一数组前缀和
    	tp tans=0;
    	for(int i=pos;i;i-=lowbit(i))tans+=val[i];
    	return tans;
	}	
	tp sum(int pos){ //得到最终数组前缀和
    	return (pos+1)*get(val1,pos)-get(val2,pos);
	}
	
	public:
	bit_pro(int N){ //初始化
		maxn_bit=N;
		val1=new tp[maxn_bit+1]; //长度要加1
		val2=new tp[maxn_bit+1];
		std::memset(val1,0,sizeof(tp)*(maxn_bit+1)); //对指针操作,要指明操作长度
		std::memset(val2,0,sizeof(tp)*(maxn_bit+1)); 
	}
	~bit_pro(){
		delete [] val1;
		delete [] val2;
	}
	tp query(int l,int r){ //查询区间和
		return sum(r)-sum(l-1);
	}
	void modify(int l,int r,tp v){ //区间更改
		add(val1,l,v);
    	add(val1,r+1,-v);
    	add(val2,l,v*l);
    	add(val2,r+1,-v*(r+1));
	}
	#undef lowbit
};

树状数组普通版

template<typename tp>
class bit{
    #define lowbit(a) (a&(-a)) 
    private:
    int maxn_bit;
    tp *val;
    
    public:
    bit(int N){
        maxn_bit=N;
        val=new tp[maxn_bit+1];
        std::memset(val,0,sizeof(tp)*(maxn_bit+1));
    }
    ~bit(){
    	delete [] val;
	}
    void add(int pos,tp v){
    	for(int i=pos;i<=maxn_bit;i+=lowbit(i))val[i]+=v;
    }
    tp get(int pos){
    	tp tans=0;
    	for(int i=pos;i;i-=lowbit(i))tans+=val[i];
    	return tans;
    }
    #undef lowbit
};

st表

template<typename tp>
class ST{
	private:
	int maxn_st;
	tp **val;
	int *pow2;
	int *lg2;
	int max_bit;	
	public:
	ST(int N,tp *v){
		maxn_st=N+1;
		max_bit=0;
		while((1<<max_bit++)<maxn_st);
		max_bit++;
		val=new tp*[max_bit];
		for(int i=0;i<max_bit;i++)val[i]=new tp[maxn_st];
		pow2=new int[max_bit];
		lg2=new int[maxn_st];
		lg2[0]=-1;
		for(int i=1;i<maxn_st;i++)lg2[i]=lg2[i/2]+1;
		pow2[0]=1;
		for(int i=1;i<max_bit;i++ )pow2[i]=pow2[i-1]*2;
		return;
		for(int i=1;i<maxn_st;i++)val[0][i]=v[i];
		for(int i=1;i<max_bit;i++)
		for(int j=1;j<maxn_st;j++)
			if(j+pow2[i]-1<maxn_st)
				val[i][j]=std::max(val[i-1][j],val[i-1][j+pow2[i-1]]);
	} 
	~ST(){
		for(int i=0;i<max_bit;i++)delete [] val[i];
		delete [] val;
		delete [] pow2;
		delete [] lg2;
	}
	tp query(int l,int r){
		int k=lg2[r-l+1];
		return std::max(val[k][l],val[k][r-pow2[k]+1]);
	}
};

trie树

template<typename tp,typename tpv=int>
class trie{
	#define maxn_c 26
	private:
	struct node{
		node **son=new node*[maxn_c];
		tpv val;
		node(){
			memset(son,0,sizeof(node*)*maxn_c);
			val=0;
		}
	};
	
	public:
	node *root=new node;
	inline int cal(tp S){
		return *S-'a';
	}
	void insert(node *x,tp S){
		if(*S==0){
			x->val++; 
			return;
		}
		int v=cal(S); 
		if(!x->son[v])x->son[v]=new node;
		insert(x->son[v],S+1);
	}
	void query(node *x,tp S){
		if(!S[dep])return;
		int v=cal(S+dep);
		if(x->son[v])query(x->son[v],S+1); 
	}
	#undef maxn_c
};

manacher

template<typename tp>
class manacher{
	private:
	tp *S;
	int *r,tot;
	void transform(tp *bg,tp *ed){
		S[0]='!';
		S[1]='#';
		tot=2;
		for(tp *i=bg;i!=ed;i++){
			S[tot++]=*i;
			S[tot++]='#';
		}
		S[tot]=0;
	}
	int work(){
		int maxright=-1,mid;
		for(int i=0;i<tot;i++){
			if(i<maxright)r[i]=std::min(r[mid*2-i],maxright-i);
			else r[i]=1;
			for(;S[i+r[i]]==S[i-r[i]];r[i]++);
			if(i+r[i]>maxright){
				mid=i;
				maxright=i+r[i];
			}
		}
		int ans=0;
		for(int i=0;i<tot;i++)ans=std::max(ans,r[i]-1);
		return ans;
	}
	
	public:
	manacher(int N){
		r=new int[(N+5)<<1];
		S=new tp[(N+5)<<1];
	}
	~manacher(){
		delete [] r;
		delete [] S;
	}
	int solve(tp *bg,tp *ed){
		transform(bg,ed);
		return work();
	}
};

FFT

#define tpv double
class cpx{
    public:
    tpv r,i;
    cpx(tpv a=0.0,tpv b=0.0){
        r=a,i=b;
    }
    cpx operator *(const cpx &p)const{
        return cpx(r*p.r-i*p.i,r*p.i+i*p.r);
    }
    cpx operator +(const cpx &p)const{
        return cpx(r+p.r,i+p.i);
    }
    cpx operator -(const cpx &p)const{
        return cpx(r-p.r,i-p.i);
    }
    cpx operator /(const tpv &p)const{
        return cpx(r/p,i/p);
    }
};
#undef tpv

template<typename tp,typename tpv=double>
class FFT{
    #define pi 3.14159265359
    private:
    int n;
    tp *omega=NULL;
    tp *A=NULL,*B=NULL;
    void getomega(){
        delete [] omega;
        omega=new tp[n];
        for(int i=0;i<n;i++)omega[i]=tp(cos(2.0*pi/n*i),sin(2.0*pi/n*i));
    }
    void DFT(tp *v,tpv ck){
        for(int l=2;l<=n;l<<=1){
            int m=l/2;
            for(tp *p=v;p!=v+n;p+=l)
                for(int i=0;i<m;i++){
                    tp t=tp(omega[n/l*i].r,omega[n/l*i].i*ck)*p[i+m];
                    p[i+m]=p[i]-t;
                    p[i]=p[i]+t;
                }
        }
    }
    tp* getval(tp *bg,tp *ed){
        tp *val=new tp[n];
        for(int i=0;i<n;i++)if(i<ed-bg)val[i]=bg[i];
        else val[i]=tp(0.0,0.0);
        return val;
    }
    void reverse(tp *val){
        int k=0;
        while((1<<k)<n)k++;
        for(int i=0;i<n;i++){
            int t=0;
            for(int j=0;j<k;j++)if(i&(1<<j))t|=(1<<(k-j-1));
            if(i<t)std::swap(val[i],val[t]);
        }
    }
    
    public:
    tp *solve(tp *bg_A,tp *ed_A,tp *bg_B,tp *ed_B){
        int tpn=ed_A-bg_A+ed_B-bg_B-1;
        n=1;
        while(n<tpn)n<<=1;
		getomega();
		A=getval(bg_A,ed_A);
        B=getval(bg_B,ed_B);
        reverse(A);
        reverse(B);
        DFT(A,1);
        DFT(B,1);
        for(int i=0;i<n;i++)A[i]=A[i]*B[i];
        reverse(A);
        DFT(A,-1);
        for(int i=0;i<n;i++)A[i]=A[i]/n; 
		tp *ans=new tp[n];
		memcpy(ans,A,sizeof(tp)*n);		
		delete[] A;
		delete[] B;
        return ans;
    }
    #undef pi
};

矩阵乘法及快速幂

template<typename tp>
class Matrix{
	public:
	unsigned int n,m;
	tp **val;
	void clear(){
		for(int i=0;i<n;i++)
			memset(val[i],0,sizeof(tp)*m);	
	}
	Matrix(int N,int M){
		n=N,m=M;
		val=new tp*[N];
		for(int i=0;i<N;i++)val[i]=new tp[M];
		clear();
	}
	~Matrix(){
		for(int i=0;i<n;i++)delete [] val[i];
		delete [] val;
	}
	Matrix operator *(const Matrix &p)const{
		Matrix tv(n,p.m);
		for(int i=0;i<n;i++)
		for(int j=0;j<p.m;j++)
		for(int k=0;k<m;k++){
			tv.val[i][j]+=val[i][k]*p.val[k][j];
		}
		return tv;
	}
	void print(){
		for(int i=0;i<n;i++){
			for(int j=0;j<m;j++)printf("%d ",val[i][j]);
			printf("\n");
		}
	}
};
template<typename tp=int>
Matrix<tp> pow2(Matrix<tp> x,int p){
	Matrix<tp> ans(x.n,x.m);
	for(int i=0;i<x.n;i++)ans.val[i][i]=1;
	for(;p;p>>=1,x=x*x)if(p&1)ans=ans*x;
	return ans;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值