树上和图上算法合集

1、树链剖分

浅谈树链剖分

树链剖分模板

#include<bits/stdc++.h>
#define ll long long
#define INF 2147483647
#define mem(i,j) memset(i,j,sizeof(i))
#define F(i,j,n) for(register int i=j;i<=n;i++)
#define md p
using namespace std;
struct hahaha{
	int from,to,nxt;
}s[200010];
int n,m,r,p,head[200010],cnt=0,pls[1000010];
int v[100010],f[100010],son[100010];
int dep[100010],top[100010],sz[100010];
int id[1000010],vt[1000010],num=0;
inline int read(){
	int datta=0;char chchc=getchar();bool okoko=0;
	while(chchc<'0'||chchc>'9'){if(chchc=='-')okoko=1;chchc=getchar();}
	while(chchc>='0'&&chchc<='9'){datta=datta*10+chchc-'0';chchc=getchar();}
	if(okoko==1)return -datta;
	return datta;
}
inline void ins(int from,int to){
	s[++cnt].from=from;
	s[cnt].to=to;
	s[cnt].nxt=head[from];
	head[from]=cnt;
}
inline int dfs1(int from){
	int tmp=0,tmx=0,ti=0;
	for(int i=head[from];i;i=s[i].nxt){
		int to=s[i].to;
		if(to!=f[from]){
			dep[to]=dep[from]+1;
			f[to]=from;
			tmp=dfs1(to);
			sz[from]+=tmp;
			if(tmp>tmx)
				tmx=tmp,ti=to;
		}
	}
	sz[from]++;
	son[from]=ti;
	return sz[from];
}
inline void dfs2(int from,int tp){
	id[from]=++num,vt[num]=v[from];
	if(son[from])
		top[son[from]]=tp,dfs2(son[from],tp);
	for(int i=head[from];i;i=s[i].nxt){
		int to=s[i].to;
		if(to!=f[from]&&to!=son[from])
			top[to]=to,dfs2(to,to);
	}
}
struct Segment_Tree{
	#define ls u<<1
	#define rs u<<1|1
	#define mid ((l+r)>>1)
	int tree[1000010];
	void updata(int u){
		tree[u]=(tree[ls]+tree[rs])%md;
	}
	void pushdown(int u,int l,int r){
		if(!pls[u])
			return ;
		pls[ls]+=pls[u];
		pls[rs]+=pls[u];
		tree[ls]+=(mid-l+1)*(pls[u]);
		tree[rs]+=(r-mid)*(pls[u]);
		pls[u]=0;
	}
	void build_tree(int u,int l,int r){
		if(l==r){
			tree[u]=vt[l];
			return ;
		}
		build_tree(ls,l,mid);
		build_tree(rs,mid+1,r);
		updata(u);
	}
	void change(int u,int l,int r,int x,int y,int z){
		if(x<=l&&r<=y){
			pls[u]+=z;
			tree[u]+=(r-l+1)*z;
			return ;
		}
		pushdown(u,l,r);
		if(x<=mid)
			change(ls,l,mid,x,y,z);
		if(y>=mid+1)
			change(rs,mid+1,r,x,y,z);
		updata(u);
	}
	int ask(int u,int l,int r,int x,int y){
		int res=0;
		if(x<=l&&r<=y)
			return tree[u];
		pushdown(u,l,r);;
		if(x<=mid)
			res+=ask(ls,l,mid,x,y);
		if(y>=mid+1)
			res+=ask(rs,mid+1,r,x,y);
		return res;
	}
}T;
inline void cRange(int x,int y,int z){
	while(top[x]!=top[y]){
		if(dep[top[x]]<dep[top[y]])
			swap(x,y);
		T.change(1,1,n,id[top[x]],id[x],z);
		x=f[top[x]];
	}
	if(dep[x]<dep[y])
		swap(x,y);
	T.change(1,1,n,id[y],id[x],z);
}
inline int qRange(int x,int y){
	int res=0;
	while(top[x]!=top[y]){
		if(dep[top[x]]<dep[top[y]])
			swap(x,y);
		res+=T.ask(1,1,n,id[top[x]],id[x]);
		res%=md;
		x=f[top[x]];
	}
	if(dep[x]<dep[y])
		swap(x,y);
	res+=T.ask(1,1,n,id[y],id[x]);
	res%=md;
	return res;
}
inline void cTree(int x,int z){
	T.change(1,1,n,id[x],id[x]+sz[x]-1,z);
}
inline int qTree(int x){
	return T.ask(1,1,n,id[x],id[x]+sz[x]-1)%md;
}
int main(){
	n=read();m=read();r=read();p=read();
	F(i,1,n)
		v[i]=read();
	F(i,1,n-1){
		int from=read(),to=read();
		ins(from,to);ins(to,from);
	}
	dep[r]=1;
	dfs1(r);
	top[r]=r;
	dfs2(r,r);
	T.build_tree(1,1,n);
	F(p,1,m){
		int kd=read(),x,y,z;
		if(kd==1)
			x=read(),y=read(),z=read(),cRange(x,y,z);
    	if(kd==2)
			x=read(),y=read(),printf("%d\n",qRange(x,y));
		if(kd==3)
			x=read(),z=read(),cTree(x,z);
		if(kd==4)
			x=read(),printf("%d\n",qTree(x));
	}
	return 0;
}
posted @ 2018-12-26 15:22  hzf29721  阅读(239)  评论(1编辑  收藏  举报