正放的瓶塞

导航

树剖学习

树剖学习

主要分为两部分

剖分-dfs

树链的应用-线段树 LCA等

#include<iostream>
#include<cstdio>
#include<algorithm>
#define M 1001010
using namespace std;
//xx
int n,m,a[1001010],r,p;
struct note {
	int l,r,tag,sum;
}c[1001010];
//tree
int ver[M],nex[M],head[M],cnt;
int siz[M],fa[M],dep[M],son[M];
//ll
int id[M],tot,cur[M],top[M];
///////////////add
inline void add(int x,int y) {
	ver[++cnt]=y;
	nex[cnt]=head[x];
	head[x]=cnt;
}

///////////////main
void dfs1(int u) {
	siz[u]=1;
	for (int x=head[u];x;x=nex[x] ) {
		int v=ver[x];
		if(v!=fa[u]) {
			dep[v]=dep[u]+1;
			fa[v]=u;
			dfs1(v);
			siz[u]+=siz[v];
			if (siz[v]>siz[son[u]]) son[u]=v;
		}
	}
}

void dfs2(int u,int t) {
	id[u]=++tot;
	cur[tot]=a[u];
	top[u]=t;
	if (son[u]) dfs2(son[u],t);
	for (int x=head[u];x;x=nex[x]) {
		int v=ver[x];
		if (v!=fa[u]&&v!=son[u]) dfs2(v,v);
	}
}
///////////////////xianduanshu
inline int lson(int x) {return x<<1;}
inline int rson(int x) {return x<<1|1;}
inline int diss(int x) {return c[x].r-c[x].l+1;}
inline int mid(int l,int r) {return(l+r)>>1;}
inline void update(int x) {c[x].sum=c[lson(x)].sum+c[rson(x)].sum;}

void pushdown(int x) {
	if (c[x].tag) {
		c[lson(x)].sum+=c[x].tag*diss(lson(x));
		c[rson(x)].sum+=c[x].tag*diss(rson(x));
		c[lson(x)].tag+=c[x].tag;
		c[rson(x)].tag+=c[x].tag;
		c[x].tag=0;
	}
}

void build(int x,int l,int r) {
	c[x].l=l;c[x].r=r;
	if (l==r) {
		c[x].sum=cur[l];
		return;
	}
	build(lson(x),l,mid(l,r));
	build(rson(x),mid(l,r)+1,r);
	update(x);	
}

inline int query(int x,int l,int r) {
	int ans=0;
	if (c[x].l>=l&&c[x].r<=r) 
		return c[x].sum;
	pushdown(x);
	int mi=mid(c[x].l,c[x].r);
	if (l<=mi) ans+=query(lson(x),l,r);
	if (r>mi) ans+=query(rson(x),l,r);
	return ans;
}

inline void change(int x,int l,int r,int d) {
	if (c[x].l>=l&&c[x].r<=r) {
		c[x].sum+=diss(x)*d;
		c[x].tag+=d;
		return;
	}
	pushdown(x);
	int mi=mid(c[x].l,c[x].r);
	if (l<=mi) change(lson(x),l,r,d);
	if (r>mi) change(rson(x),l,r,d);
	update(x);
	return;
	
}

int calsum(int x,int y) {
	int anss=0;
	while (top[x]!=top[y]) {
		if (dep[top[x]]<dep[top[y]]) swap(x,y);
		anss+=query(1,id[top[x]],id[x]);
		x=fa[top[x]];
	}
	if (dep[x]>dep[y]) swap(x,y);
	anss+=query(1,id[x],id[y]);
	return anss;
}

inline void calchan(int x,int y,int d) {
	while (top[x]!=top[y]) {
		if (dep[top[x]]<dep[top[y]]) swap(x,y);
		change(1,id[top[x]],id[x],d);
		x=fa[top[x]];
	}
	if (dep[x]>dep[y]) swap(x,y);
	change(1,id[x],id[y],d);
}

int sonsum(int x) {
	int ans=0;
	ans+=query(1,id[x],id[x]+siz[x]-1);
	return ans;
}

inline void sonchan(int x,int d) {
	change(1,id[x],id[x]+siz[x]-1,d);
	return;
}
////////////////mainn
int main() {
	scanf("%d%d%d%d",&n,&m,&r,&p);
	for (int i=1;i<=n;i++) scanf("%d",&a[i]);
	int x,y,z;
	for (int i=1;i<n;i++) {
		scanf("%d%d",&x,&y);
		add(x,y);
		add(y,x);
	}
	dfs1(r);
	dfs2(r,r);
	build(1,1,n);
	int sc;
	while (m--) {
		scanf("%d",&sc);
		if (sc==1) {
			scanf("%d%d%d",&x,&y,&z);
			calchan(x,y,z);
		}
		if (sc==2) {
			scanf("%d%d",&x,&y);
			printf("%d\n",calsum(x,y)%p);
		}
		if (sc==3) {
			scanf("%d%d",&x,&z);
			sonchan(x,z);
		}
		if (sc==4) {
			scanf("%d",&x);
			printf("%d\n",sonsum(x)%p);
		}
	}
	return 0;
}

posted on 2021-07-12 11:06  正放的瓶塞  阅读(30)  评论(0)    收藏  举报