ACM 各種模板整理

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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章