省选模板复习—【数据结构】

树状数组


线段树


平衡树

fhqtreapfhq-treap

inline int newnode(int k){
	int u=++tot;key[tot]=rnd(),val[tot]=k;
	siz[tot]=1;return tot;
}
inline void pushup(int u){
	siz[u]=siz[lc(u)]+siz[rc(u)]+1;
}
inline void split(int u,int &r1,int &r2,int k){
	if(!u){r1=r2=0;return;}
	if(val[u]<=k){//这是<= 
		r1=u;split(rc(u),rc(r1),r2,k);
	}
	else r2=u,split(lc(u),r1,lc(r2),k);
	pushup(u);
}
inline void merge(int &u,int r1,int r2){
	if(!r1||!r2){u=r1+r2;return;}
	if(key[r1]<key[r2]){
		u=r1,merge(rc(u),rc(r1),r2);
	}
	else u=r2,merge(lc(u),r1,lc(r2));
	pushup(u);
}
inline int find(int u,int k){
	while(siz[lc(u)]+1!=k){
		if(siz[lc(u)]>=k)
			u=lc(u);
		else k-=siz[u]-siz[rc(u)],u=rc(u);
	}
	return u;
}
inline void insert(int k){
	int u=newnode(k),r1,r2;
	split(rt,r1,r2,k);
	merge(r1,r1,u);
	merge(rt,r1,r2);
}
inline void delet(int k){
	int r1,r2,r3;
	split(rt,r1,r2,k-1);
	split(r2,r2,r3,k);
	merge(r2,lc(r2),rc(r2));
	merge(r1,r1,r2);
	merge(rt,r1,r3);
}
inline int rank(int k){
	int r1,r2;
	split(rt,r1,r2,k-1);
	int res=siz[r1]+1;
	merge(rt,r1,r2);
	return res;
}
inline int getval(int k){
	return val[find(rt,k)];
}
inline int pre(int k){
	int r1,r2;
	split(rt,r1,r2,k-1);
	int u=find(r1,siz[r1]);
	merge(rt,r1,r2);
	return val[u];
}
inline int nxt(int k){
	int r1,r2;
	split(rt,r1,r2,k);
	int u=find(r2,1);
	merge(rt,r1,r2);
	return val[u];
}

LCT

inline bool isrc(int u){
	return rc(fa[u])==u;
}
inline bool isrt(int u){
	if(!fa[u])return 1;
	return lc(fa[u])!=u&&rc(fa[u])!=u;
}
inline void pushup(int u){
	val[u]=a[u];
	if(lc(u))val[u]+=val[lc(u)];
	if(rc(u))val[u]+=val[rc(u)];
}
inline void pushdown(int u){
	if(!rev[u])return;
	swap(lc(u),rc(u));		
	if(lc(u))rev[lc(u)]^=1;
	if(rc(u))rev[rc(u)]^=1;
	rev[u]=0;
}
inline void rotate(int v){
	int u=fa[v],z=fa[u];
	int t=rc(u)==v;
	if(!isrt(u))son[z][rc(z)==u]=v;//判断 
	fa[v]=z;
	son[u][t]=son[v][t^1],fa[son[v][t^1]]=u;
	son[v][t^1]=u,fa[u]=v;
	pushup(u),pushup(v);//顺序 
}
inline void splay(int u){
	q[q[0]=1]=u;
	for(int v=u;!isrt(v);v=fa[v])q[++q[0]]=fa[v];
	for(int i=q[0];i;i--)pushdown(q[i]);//先pushdown 
	while(!isrt(u)){
		if(!isrt(fa[u])){
			if(isrc(u)==isrc(fa[u]))rotate(fa[u]);
			else rotate(u);
		}
		rotate(u);
	}
	pushup(u);
}
inline void access(int u){
	for(int v=0;u;v=u,u=fa[u]){
		splay(u),rc(u)=v;
		if(v)fa[v]=u;
		pushup(u);
	}
}
inline int findrt(int u){
	access(u),splay(u);
	while(pushdown(u),lc(u))u=lc(u);//pushdown
	splay(u);return u;
}
inline void makert(int u){
	access(u),splay(u),rev[u]^=1;
}
inline void link(int u,int v){
	makert(u),fa[u]=v;
}
inline void cut(int u,int v){
	makert(u),access(v),splay(v);
	lc(v)=fa[u]=0,pushup(v);
}
inline int query(int u,int v){
	makert(u),access(v),splay(v);return val[v];
}

维护子树

multiset<int>chain[N];//注意是multiset
inline int fir(int u){
	return chain[u].size()?*chain[u].rbegin():-inf;
}
inline void access(int u){
	for(int v=0;u;v=u,u=fa[u]){
		splay(u);
		if(rc(u))chain[u].insert(lmx[rc(u)]);
		if(v)chain[u].erase(chain[u].find(lmx[v]));
		rc(u)=v;
		pushup(u);
	}
}

STST表求LcaLca(四倍空间)
注意二维哪一维在前(二维寻址常数优化(13大约frac 1 3))

void dfs(int u,int fa){
	st[0][++dfn]=u;pos[u]=dfn;
	for(int e=adj[u];e;e=nxt[e]){
		int v=to[e];
		if(v==fa)continue;
		dep[v]=dep[u]+1;
		dfs(v,u),st[0][++dfn]=u;
	}
}
void init(){
	dfs(1,0);lg[0]=-1;
	for(int i=1;i<=dfn;i++)lg[i]=lg[i>>1]+1;
	for(int i=1;(1<<i)<=dfn;i++){
		for(int j=1;j+(1<<i)-1<=dfn;j++){
			int x1=st[i-1][j],x2=st[i-1][j+(1<<(i-1))];
			st[i][j]=dep[x1]>dep[x2]?x2:x1;
		}
	}
}
inline int ask(int u,int v){
	int x=pos[u],y=pos[v];
	if(x>y)swap(x,y);
	int t=lg[y-x+1];
	int x1=st[t][x],x2=st[t][y-(1<<t)+1];
	return dep[x1]>dep[x2]?x2:x1;
}
void dfs(int u,int f){
    st[0][++dfn]=dis[u],pos[u]=dfn;
    for(int e=adj[u];e;e=nxt[e]){
        int v=to[e];
        if(v==f)continue;
        dis[v]=dis[u]+1;
        dfs(v,u);
        st[0][++dfn]=dis[u];
    }
}
inline void init(){
    dfs(1,0),lg[0]=-1;
    for(int i=1;i<=dfn;i++)lg[i]=lg[i>>1]+1;
    for(int i=1;(1<<i)<=dfn;i++){
        for(int j=1;j+(1<<i)-1<=dfn;j++){
            st[i][j]=min(st[i-1][j],st[i-1][j+(1<<(i-1))]);
        }
    }
}
inline int dist(int u,int v){
    int x=pos[u],y=pos[v];
    if(x>y)swap(x,y);
    int t=lg[y-x+1];
    return dis[u]+dis[v]-2*min(st[t][x],st[t][y-(1<<t)+1]);
}

长剖

(注意dep[v]dep[v]的范围以及边界(最好每次多开大点但相应数组就要开nmoren*more))

int *f[N],tmp[N],*id=tmp;
void dfs1(int u,int fa){
	for(int e=adj[u];e;e=nxt[e]){
		int v=to[e];
		if(v==fa)continue;
		dfs1(v,u);
		if(dep[v]>dep[son[u]])son[u]=v;
	}
	dep[u]=dep[son[u]]+1;
}
void dfs2(int u,int fa){
	if(son[u]){f[son[u]]=f[u]+1,dfs2(son[u],u);}
	for(int e=adj[u];e;e=nxt[e]){
		int v=to[e];
		if(v==fa||v==son[u])continue;
		f[v]=id,id+=dep[v],dfs2(v,u);
		for(int i=0;i<dep[v];i++)calc....;
	}
}
int main(){
	dfs1(1,0);
	f[1]=id,id+=dep[1];
	dfs2(1,0);
}

虚树

(注意clearclear

inline void solve(){
	stk[top=1]=a[1];
	for(int i=2;i<=num;i++){
		int lca=Lca(stk[top],a[i]);
		while(dfn[lca]<dfn[stk[top]]){
			if(dfn[lca]>=dfn[stk[top-1]]){
				G2.addedge(lca,stk[top--]);
				if(stk[top]!=lca)stk[++top]=lca;
				break;
			}
			G2.addedge(stk[top-1],stk[top]),top--;
		}
		stk[++top]=a[i];
	}
	while(top>1)G2.addedge(stk[top-1],stk[top]),top--;
	solve(),clear();
}

倍增求lcalca注意dep[1]=1dep[1]=1


动态点分治:

inline int query(int u,int k){
    int res=0;
    for(int i=u;i;i=fa[i]){
        res+=f1[i].query(k-dist(i,u));
    }
    for(int i=u;fa[i];i=fa[i]){
        res-=f2[i].query(k-dist(fa[i],u));
    }
    return res;
}

注意计算distdist一个是和当前centercenter一个是和fafa
一个是判当前有没有一个是父亲有没有

细节:son[0],maxn,dep[v]=val[e]son[0],maxn,dep[v]=val[e]……


Kruscal重构树

重构树要开2倍空间
dfs(tot)dfs(tot)
unule n

(ReturnReturn)

struct edge{
	int u,v,w;
	friend inline bool operator <(const edge &a,const edge &b){
		return a.w>b.w;
	}
}e[N];
int tot,lc[N],rc[N],fa[N],f[N][22],val[N],g[N];//2倍空间 
inline int find(int x){
	return fa[x]==x?fa[x]:fa[x]=find(fa[x]);
}
void dfs(int u){
	for(int i=1;i<=20;i++)f[u][i]=f[f[u][i-1]][i-1];
	if(u<=n){//
		g[u]=dis[u];return;
	}
	dfs(lc[u]),dfs(rc[u]),g[u]=min(g[lc[u]],g[rc[u]]);
}
inline void kruscal(){
	sort(e+1,e+m+1);
	for(int i=1,cnt=0;i<=m&&cnt<n-1;i++){
		int f1=find(e[i].u),f2=find(e[i].v);
		if(f1!=f2){
			fa[f1]=fa[f2]=fa[++tot]=tot;
			val[tot]=e[i].w;
			lc[tot]=f1,rc[tot]=f2;
			f[f1][0]=f[f2][0]=tot;cnt++;
		}
	}
	dfs(tot);
}
int get(int u,int p){
	for(int i=20;~i;i--){
		if(fa[u][i]&&val[f[u][i]]>p)u=f[u][i];//神tm高速缓存优化三维寻址 
	}
	return g[u];
}
原文地址:https://www.cnblogs.com/stargazer-cyk/p/11145558.html