CSP前算法模板复习

强联通分量模板

void tarjan(int x){
    dfn[x]=low[x]=++Time;
    stk[++top]=x;
    for(int i=head[x];~i;i=e[i].nxt){
        int v=e[i].v;
        if(!dfn[v]){
            tarjan(v);
            chkmin(low[x],low[v]);
        }
        else if(!color[v])chkmin(low[x],dfn[v]);        
    }
    if(low[x]==dfn[x]){
        ++color_cnt;
        do color[stk[top]]=color_cnt;while(top&&stk[top--]!=x);
    }
}

割点模板

void tarjan(int x,int rt){
    int cnt=0;
    dfn[x]=low[x]=++Time;
    for(int i=head[x];~i;i=e[i].nxt){
        int v=e[i].v;
        if(!dfn[v]){
            fa[v]=x;
            tarjan(v,rt);
            chkmin(low[x],low[v]);
            if(low[v]>=dfn[x]&&u!=rt)cut[x]=1;
            if(x==rt)++cnt;
        }
        else if(fa[x]!=v) chkmin(low[x],dfn[v]);
    }
    if(x==rt&&cnt>=2)cut[x]=1;
}

割边模板

void tarjan(int x,int fa){
    dfn[x]=low[x]=++Time;
    for(int i=head[x];~i;i=e[i].nxt){
        int v=e[i].v;
        if(!dfn[v]){
            tarjan(v,x);
            chkmin(low[x],low[v]);
            if(low[v]>dfn[x])cut[i]=1;
        }
        else if(v!=fa)chkmin(low[x],dfn[v]);
    }
}

最小生成树:Kruskal算法

inline void Kruskal(){
    sort(e+1,e+m+1);
    int cnt=0,ans=0;
    for(int i=1;i<=m;++i)
    {
        int u=find(e[i].u),v=find(e[i].v),w=e[i].w;
        if(u!=v)
        {
            fa[u]=v;
            ans+=w;
	        ++cnt;
        }
        if(cnt==n-1)break;
	}
}

堆优化Prim算法

typedef pair<int,int> pii;
priority_queue<pii,vector<pii>,greater<pii> >pq;
inline void Prim()
{
    int cnt=0,ans=0;
   	memset(dis,127,sizeof dis);
    while(!pq.empty())
    {
        pii now=pq.top();pq.pop();
        if(vis[now.second])continue;
        vis[now.second]=1;
        ans+=now.first;
        for(int i=head[now.first];~i;i=e[i].nxt){
            int v=e[i].v;
            if(e[i].w<dis[v])
                dis[v]=e[i].w,pq.push(pii(dis[v],v));
        }
        ++cnt;
        if(cnt==n-1)break;
    }
}

01背包

const int N=1e3+7;
int f[N],w[N],c[N];
int main(void)
{
	int n=gi,V=gi;
	for(int i=1;i<=n;++i)c[i]=gi,w[i]=gi;
	for(int i=1;i<=n;++i)
		for(int j=V;j>=a[i];--j)
			chkmax(f[j],f[j-c[i]]+w[i]);
	return 0;
}

完全背包

const int N=1e3+7;
int f[N],w[N],c[N];
int main(void)
{
	int n=gi,V=gi;
	for(int i=1;i<=n;++i)c[i]=gi,w[i]=gi;
	for(int i=1;i<=n;++i)
		for(int j=a[i];j<=V;++j)
			chkmax(f[j],f[j-c[i]]+w[i]);
	return 0;
}

多重背包

略,(单调队列我也不会啊)

树状数组

struct BIT{
	int c[N];
    inline void add(int x,int y){
        for(;x<=n;x+=x&-x)c[x]+=y;
    }
    inline int query(int x){
        int ret=0;
        for(;x;x-=x&-x)ret+=c[x];
        return ret;
    }
};

线段树

const int N=1e5+7;
struct SegmentTree{
	int sum[N<<2],tag[N<<2];
	#define ls (rt<<1)
	#define rs (rt<<1|1)
	#define mid ((l+r)>>1)
	inline void pushtag(int rt,int l,int r,int v){
		tag[rt]+=v,sum[rt]+=(r-l+1)*v;
	}
	inline void pushdown(int rt,int l,int r)
	{
		if(tag[rt]){
			pushtag(ls,l,mid,tag[rt]);
			pushtag(rs,mid+1,r,tag[rt]);
			tag[rt]=0;
		}
	}
	inline void pushup(int rt){
		sum[rt]=sum[ls]+sum[rs];
	}
	inline void modify(int rt,int l,int r,int L,int R,int v){
		if(L<=l&&r<=R){
			pushtag(rt,l,r,v);
			return;
		}
		pushdown(rt,l,r);
		if(L<=mid)modify(ls,l,mid,L,R,v);
		if(R>mid)modify(rs,mid+1,r,L,R,v);
		pushup(rt);
	}
	inline int query(int rt,int l,int r,int L,int R){
		if(L<=l&&r<=R)return sum[rt];
		pushdown(rt,l,r);
		int ret=0;
		if(L<=mid)ret+=query(ls,l,mid,L,R);
		if(R>mid)ret+=query(rs,mid+1,r,L,R);
		return ret;
	}
};

Miller_Rabin

bool Test(ll a,ll x)
{
    if(a>=x)return 1;
    ll ret=qpow(a,x-1,x),s=x^1;
    while(ret==1&&!(s&1))s>>=1,ret=qpow(a,s,x);
    return ret==1||ret==(x^1);
}
/*
可以从后往前检测,似乎会更快
bool Test(ll a,ll x)
{
	if(a>=x)return 1;
	ll ret,s=x^1;
	int p=__builtin_ctzll(s);
	ret=qpow(a,s>>p,x);
	if(ret==1||ret==(x^1))return 1;
	while(p--&&ret!=(x^1))ret=mul(ret,ret,x);
	return p>=0;
}
*/

线性筛

int npr[N],pr[N],cnt;
void sieve(int n)
{
    npr[1]=1;
    for(int i=2;i<=n;++i){
        if(!npr[i]){
            pr[++cnt]=i;
        }
        for(int j=1;j<=cnt&&pr[j]*i<=n;++j)
        {
            npr[pr[j]*i]=1;
            if(i%pr[j]==0)break;
        }
    }
}

普通平衡树

const int N=1e5+7;
int top,cnt;
struct SplayTree{
	struct node;
	typedef node* tree;
	struct node{
		int val,siz,cnt;
		tree par,ch[2];
		node(){}
		node(int v,tree fa):val(v),siz(1),cnt(1),par(fa){ch[0]=ch[1]=NULL;}
	}*root;
	static node pool[N<<2],*stk[N<<2];
	inline tree newnode(int val,tree par){return &(*(top?stk[top--]:pool+(++cnt))=node(val,par));}
	inline void delnode(tree &x){stk[++top]=x,x=NULL;}
	inline int siz(tree x){return x?x->siz:0;}
	inline bool ws(tree x,tree p){return p?p->ch[1]==x:0;}
	inline void pushup(tree x){if(x)x->siz=siz(x->ch[0])+siz(x->ch[1])+x->cnt;}
	inline void connect(tree x,tree p,bool wson){x?x->par=p:0,(p?p->ch[wson]:root)=x;}
	inline void rotate(tree x){
		tree p=x->par,g=p->par;
		bool t=ws(x,p);
		connect(x,g,ws(p,g));
		connect(x->ch[!t],p,t);
		connect(p,x,!t);
		pushup(p);
	}
	inline tree adjust(tree x,bool p,bool q)
	{
		tree k=x->ch[p];
		while(k&&k->ch[q])k=k->ch[q];
		return Splay(k,x),x;
	}
	inline tree Splay(tree x,tree y=NULL){
		while(x&&x->par!=y){
			tree p=x->par,g=p->par;
			if(g!=y)rotate(ws(x,p)^ws(p,g)?x:p);
			rotate(x);
		}
		return pushup(x),x;
	}
	inline tree find(int val){
		tree x=root;
		while(x&&x->val!=val&&x->ch[val>x->val])x=x->ch[val>x->val];
		return Splay(x),x;
	}
	inline tree findkth(int k){
		tree x=root;
		while(x)
			if(siz(x->ch[0])+x->cnt>=k&&siz(x->ch[0])<k)return x;
			else if(siz(x->ch[0])>=k)x=x->ch[0];
			else k-=siz(x->ch[0])+x->cnt,x=x->ch[1];
		assert(0);
	}
	inline void erase(int val){
		tree x=find(val);
		if(x->cnt>1)return --x->cnt,void();
		adjust(x,0,1);
		connect(x->ch[0],NULL,0),connect(x->ch[1],root,1);
		delnode(x);
	}
	inline tree insert(int val){
		if(!root)return root=newnode(val,NULL);
		for(tree x=root;x;x=x->ch[val>x->val])
		{
			if(x->val==val)return ++x->cnt,Splay(x);
			if(!x->ch[val>x->val])return Splay(x->ch[val>x->val]=newnode(val,x));
		}
	}
	inline int rank(int x){return siz(find(x)->ch[0])+1;}
	inline tree pre(int x){
		tree tmp=adjust(insert(x),0,1)->ch[0];
		return erase(x),tmp;
	}
	inline tree nxt(int x){
		tree tmp=adjust(insert(x),1,0)->ch[1];
		return erase(x),tmp;
	}
}bt;
SplayTree::node SplayTree::pool[N<<2],*SplayTree::stk[N<<2];

单源最短路(堆优化\(dijkstra\))

typedef pair<int,int> pii;
priority_queue<pii,vector<pii>,greater<pii> >Q;
int vis[N],dis[N];
inline void dijkstra(){
	memset(dis,127,sizeof dis);
    dis[S]=0;
    Q.push(pii(0,S));
    while(!Q.empty())
    {
        int now=Q.top().second;Q.pop();
        if(vis[now])continue;
        vis[now]=1;
        for(int i=head[now];~i;i=e[i].nxt){
            int v=e[i].v;
            if(dis[v]>dis[now]+e[i].w){
                dis[v]=dis[now]+e[i].w;
                if(!vis[v])Q.push(pii(dis[v],v));
            }
        }
    }
}

单源最短路\(SPFA\)

int dis[N],vis[N];
queue<int>Q;
inline void spfa()
{
    memset(dis,127,sizeof dis);
    dis[S]=0;
    Q.push(S);
    while(!Q.empty())
    {
        int now=Q.front();Q.pop();
        vis[now]=0;
        for(int i=head[now];~i;i=e[i].nxt){
            int v=e[i].v;
            if(dis[v]>dis[now]+e[i].w){
                dis[v]=dis[now]+e[i].w;
                if(!vis[now])Q.push(now),vis[now]=1;
            }
        }
	}
}

\(ST\)

#define lg2(x) (31-__builtin_clz(x))
int f[21][N],a[N];
inline void STinit(int n){
    int len=lg2(n);
   	for(int i=1;i<=n;++i)f[0][i]=a[i];
    for(int i=1;i<=len;++i)
        for(int j=1;j+(1<<i)-1<=n;++j)
            f[i][j]=min(f[i-1][j],f[i-1][j+(1<<i)-1]);
}
inline int Query(int l,int r){
    if(l>r)swap(l,r);
    int k=lg2(r-l+1);
    return min(f[k][l],f[k][r-(1<<k)+1]);
}

文艺平衡树

struct SplayTree{
	struct node;
	typedef node* tree;
	struct node{
		int val,siz,rev;
		tree par,ch[2];
		node(){}
		node(int v,tree fa):val(v),siz(1),rev(0),par(fa){ch[0]=ch[1]=NULL;}
	}*root;
	inline int siz(tree x){return x?x->siz:0;}
	inline bool ws(tree x,tree p){return p?p->ch[1]==x:0;}
	inline void connect(tree x,tree p,bool which){x?x->par=p:0,(p?p->ch[which]:root)=x;}
	inline void pushup(tree x){if(x)x->siz=siz(x->ch[0])+siz(x->ch[1])+1;}
	inline void pushtag(tree x){if(x)std::swap(x->ch[0],x->ch[1]),x->rev^=1;}
	inline void pushdown(tree x){if(x&&x->rev)pushtag(x->ch[0]),pushtag(x->ch[1]),x->rev=0;}
	inline int size(){return siz(root);}
	inline void rotate(tree x)
	{
		tree p=x->par,g=p->par;
		bool t=ws(x,p);
		connect(x,g,ws(p,g));
		connect(x->ch[!t],p,t);
		connect(p,x,!t);
		pushup(p);
	}
	inline tree Splay(tree x,tree y=NULL)
	{
		while(x&&x->par!=y){
			tree p=x->par,g=p->par;
			if(g!=y)rotate(ws(x,p)^ws(p,g)?x:p);
			rotate(x);
		}
		return pushup(x),x;
	}
	inline tree adjust(tree x,bool p,bool q){
		tree k=x->ch[p];
		while(k&&k->ch[q])k=k->ch[q];
		return Splay(k,x),x;
	}
	inline tree findkth(int k){
		if(k<1||k>size())return NULL;
		tree x=root;
		while(x)
		{
			pushdown(x);
			if(siz(x->ch[0])+1==k)return x;
			else if(siz(x->ch[0])>=k)x=x->ch[0];
			else k-=siz(x->ch[0])+1,x=x->ch[1];
		}
	}
	inline tree split(int l,int r){
		if(l>r)return NULL;
		tree L=findkth(l-1),R=findkth(r+1);
		Splay(L),Splay(R,L);
		return l==1&&r==size()?root:(l==1?root->ch[0]:(r==size()?root->ch[1]:root->ch[1]->ch[0]));
	}
	inline void reverse(int l,int r){
		tree x=split(l,r);
		pushtag(x);
	}
	inline void merge(tree &a,tree &b){
		if(!a)return std::swap(b,a),void();
		if(!b)return;
		if(a->ch[1])
		{
			adjust(a,1,1);
			connect(b,a->ch[1],1);
			pushup(a->ch[1]);
		}
		else connect(b,a,1);
		pushup(a);
	}
	inline tree cut(tree x){
		if(!x)return NULL;
		tree p=x->par;
		if(p)p->ch[ws(x,p)]=0;
		x->par=0;
		return pushup(p),p;
	}
	inline void swap(int l1,int r1,int l2,int r2){
		int siz1=r1-l1+1,siz2=l2-r1-1,siz3=r2-l2+1;
		tree a=split(1,l1-1);cut(a);
		tree b=split(1,siz1);cut(b);
		tree c=split(1,siz2);cut(c);
		tree d=split(1,siz3),e=cut(d);
		merge(a,d),merge(a,c),merge(a,b),merge(a,e);
		root=a;
	}
	inline tree insert(int val){
		if(!root)return root=new node(val,NULL);
		if(root->ch[1])
		{
			adjust(root,1,1);
			return Splay(root->ch[1]->ch[1]=new node(val,root->ch[1]));
		}
		return Splay(root->ch[1]=new node(val,root));
	}
	inline void print(){_print(root);}
	inline void _print(tree x){
		if(!x)return ;
		pushdown(x);
		_print(x->ch[0]);
		pi(x->val,' ');
		_print(x->ch[1]);
	}
	inline tree build(int l,int r,int a[]){
		if(l>r)return NULL;
		int mid=(l+r)>>1;
		tree x=new node(a[mid],NULL);
		connect(build(l,mid-1,a),x,0);
		connect(build(mid+1,r,a),x,1);
		return pushup(x),x;
	}
	inline void rebuild(int n,int a[]){root=build(1,n,a);}
	inline void join(SplayTree &b){merge(root,b.root);}
};
posted @ 2019-11-10 15:50  Adscn  阅读(365)  评论(0编辑  收藏  举报