树链剖分

重链剖分

宏定义

  • #define pl p<<1\texttt{\#define pl p<<1}:线段树中点 pp 的左儿子。
  • #define pr p<<1|1\texttt{\#define pr p<<1|1}:线段树中点 pp 的右儿子。
  • #define pf a[p].fa\texttt{\#define pf a[p].fa}:树链剖分的树中点 pp 的父节点。
  • #define pde a[p].dep\texttt{\#define pde a[p].dep}:树链剖分的树中节点 pp 的深度,根节点深度为 11
  • #define psi a[p].sze\texttt{\#define psi a[p].sze}:树链剖分的树中点 pp 的子树大小。
  • #define pte a[p].ted\texttt{\#define pte a[p].ted}:树链剖分的树中点 pp 的子树的末尾节点。
  • #define pdf a[p].dfn\texttt{\#define pdf a[p].dfn}:树链剖分的树中点 ppdfn\text{dfn} 序。
  • #define pso a[p].son\texttt{\#define pso a[p].son}:树链剖分的树中点 pp 的重儿子。
  • #define pt a[p].top\texttt{\#define pt a[p].top}:树链剖分的树中点 pp 所在的链的链顶节点。
  • #define pc a[p].ced\texttt{\#define pc a[p].ced}:树链剖分的树中点 pp 所在的链的链尾节点。

变量

  • const TCP_T inf\texttt{const TCP\_T inf}:一个极大值。
  • struct Segment_Tree\texttt{struct Segment\_Tree}线段树部分。
  • int a[p].fa\texttt{int a[p].fa}:同 pf\texttt{pf}
  • int a[p].dep\texttt{int a[p].dep}:同 pde\texttt{pde}
  • int a[p].dfn\texttt{int a[p].dfn}:同 pdf\texttt{pdf}
  • int a[p].sze\texttt{int a[p].sze}:同 psi\texttt{psi}
  • int a[p].ted\texttt{int a[p].ted}:同 pte\texttt{pte}
  • int a[p].son\texttt{int a[p].son}:同 pso\texttt{pso}
  • int a[p].top\texttt{int a[p].top}:同 pt\texttt{pt}
  • int a[p].ced\texttt{int a[p].ced}:同 pc\texttt{pc}
  • int cnt\texttt{int cnt}:用于求 dfn\text{dfn} 序。
  • int rnk[i]\texttt{int rnk[i]}:线段树的第 ii 个位置对应的树链剖分的树的节点编号。

函数

  • void dfs1(int p)\texttt{void dfs1(int p)}:第一次深搜。
  • int dfs2(int p,int q)\texttt{int dfs2(int p,int q)}:第二次深搜。
  • void init(int root,int n)\texttt{void init(int root,int n)}:对节点数为 nn,根节点为 rootroot 的树进行树链剖分。
  • void change1(int u,int v,TCP_T z)\texttt{void change1(int u,int v,TCP\_T z)}:在树上的路径 uvu\rightarrow v 进行修改,zz 是修改参数。
  • void change2(int p,TCP_T z)\texttt{void change2(int p,TCP\_T z)}:在以 pp 为根的子树进行修改,zz 是修改参数。
  • TCP_T ask1(int u,int v)\texttt{TCP\_T ask1(int u,int v)}:求 树上的路径 uvu\rightarrow v 的答案。
  • TCP_T ask2(int p)\texttt{TCP\_T ask2(int p)}:求以 pp 为根的子树的答案。

代码

#define pl p<<1
#define pr p<<1|1
#define pf a[p].fa
#define pde a[p].dep
#define psi a[p].sze
#define pte a[p].ted
#define pdf a[p].dfn
#define pso a[p].son
#define pt a[p].top
#define pc a[p].ced
#define TCP_T ll
const TCP_T inf=1e9;
struct Segment_Tree{
    struct Tree{
        int l,r;
        int tag;
        TCP_T val;
    }a[N*4];
    void pushup(int p){
        ;
    }
    void pushdown(int p){
        ;
    }
    void build(int p,int l,int r,int *rnk){
        a[p].l=l;
        a[p].r=r;
        if(l==r){
            ;
            return;
        }
        int mid=(l+r)>>1;
        build(pl,l,mid,rnk);
        build(pr,mid+1,r,rnk);
        pushup(p);
    }
    void change(int p,int l,int r,TCP_T v){
        if(l<=a[p].l&&a[p].r<=r){
            ;
            return;
        }
        pushdown(p);
        int mid=(a[p].l+a[p].r)>>1;
        if(l<=mid)
            change(pl,l,r,v);
        if(r>mid)
            change(pr,l,r,v);
        pushup(p);
    }
    TCP_T ask(int p,int l,int r){
        if(l<=a[p].l&&a[p].r<=r){
            ;
            return ;
        }
        pushdown(p);
        int mid=(a[p].l+a[p].r)>>1;
        TCP_T ans=0;
        if(l<=mid)
            ans+=ask(pl,l,r);
        if(r>mid)
            ans+=ask(pr,l,r);
        return ans;
    }
}tree;
struct TCP{
	struct Node{
		int fa,dep,dfn;//self
		int sze,ted;//tree
		int son,top,ced;//chain
	}a[N];
	int cnt,rnk[N];
	void dfs1(int p){
		pso=-1;
		psi=1;
		for(int i=head[p];i;i=nxt[i]){
			int y=ver[i];
			if(!a[y].dep){
				a[y].dep=pde+1;
				a[y].fa=p;
				dfs1(y);
				psi+=a[y].sze;
				if(pso==-1||a[y].sze>a[pso].sze)
					pso=y;
			}
		}
	}
	int dfs2(int p,int q){
		pt=q;
		pdf=++cnt;
		rnk[cnt]=pte=p;
		if(pso==-1){
			int ted=pte;
			pc=cnt;
			while(p!=q){
				p=pf;
				pc=cnt;
			}
			return ted;
		}
		pte=dfs2(pso,q);
		for(int i=head[p];i;i=nxt[i]){
			int y=ver[i];
			if(y!=pso&&y!=pf)
				pte=dfs2(y,y);
		}
		return pte;
	}
	void init(int root,int n){
		cnt=0;
		a[root].dep=1;
		dfs1(root);
		dfs2(root,root);
		tree.build(1,1,n,rnk);
	}
	void change1(int u,int v,TCP_T z){
		int fu=a[u].top,fv=a[v].top;
		while(fu^fv){
			if(a[fu].dep>=a[fv].dep){
				tree.change(1,a[fu].dfn,a[u].dfn,z);
				u=a[fu].fa;
			}
			else{
				tree.change(1,a[fv].dfn,a[v].dfn,z);
				v=a[fv].fa;
			}
			fu=a[u].top;
			fv=a[v].top;
		}
		tree.change(1,min(a[u].dfn,a[v].dfn),max(a[u].dfn,a[v].dfn),z);
	}
	void change2(int p,TCP_T z){
		tree.change(1,pdf,a[pte].dfn,z);
	}
	TCP_T ask1(int u,int v){
		TCP_T ans=0;
		int fu=a[u].top,fv=a[v].top;
		while(fu^fv){
			if(a[fu].dep>=a[fv].dep){
				ans=ans+tree.ask(1,a[fu].dfn,a[u].dfn);
				u=a[fu].fa;
			}
			else{
				ans=ans+tree.ask(1,a[fv].dfn,a[v].dfn);
				v=a[fv].fa;
			}
			fu=a[u].top;
			fv=a[v].top;
		}
		ans=ans+tree.ask(1,min(a[u].dfn,a[v].dfn),max(a[u].dfn,a[v].dfn));
		return ans;
	}
	TCP_T ask2(int p){
		return tree.ask(1,pdf,a[pte].dfn);
	}
}tr;
posted @ 2022-11-19 22:31  luckydrawbox  阅读(6)  评论(0)    收藏  举报  来源