树剖 20pts 求调
查看原帖
树剖 20pts 求调
515129
TLEWA楼主2022/11/21 17:03

rt,qwq

#include<bits/stdc++.h>
using namespace std;

const int N=100050,M=200050;
int n,m,r;
long long mod;
int fa[N],size[N],dep[N],son[N],dfn[N],top[N];
int val[N];

struct Node {
	int to,next;
}arr[M];
int first[N],p;

void add(int u,int v) {
	arr[++p].to=v;
	arr[p].next=first[u];
	first[u]=p;
}

struct Tree {
	int l,r;
	long long add,sum;
}tre[N*4];

inline int ls(int p){return p<<1;}
inline int rs(int p){return p<<1|1;}

void pushup(int u) {tre[u].sum=(tre[ls(u)].sum+tre[rs(u)].sum)%mod;}
void pushdown(int u) {
	auto &root=tre[u],&lson=tre[ls(u)],&rson=tre[rs(u)];
	if(root.add) {
		lson.add+=root.add,lson.sum+=root.add*(lson.r-lson.l+1);
		lson.add%=mod;
		rson.add+=root.add,rson.sum+=root.add*(rson.r-rson.l+1);
		lson.add%=mod;
		root.add=0;
	}
//	cout << "123123fsdfs" << endl;
}

void build(int u,int l,int r) {
	tre[u].l=l,tre[u].r=r,tre[u].add=0,tre[u].sum=0;
	if(l==r) return;
	int mid=(l+r)/2;
	build(ls(u),l,mid);
	build(rs(u),mid+1,r);
	pushup(u);
}

void plu(int u,int l,int r,int k) {
	if(l<=tre[u].l&&r>=tre[u].r) tre[u].add+=k,tre[u].sum+=k*(tre[u].r-tre[u].l+1);
	else {
		pushdown(u);
		int mid=(tre[u].l+tre[u].r)/2;
//		cout << mid << ' ' << tre[u].l << ' ' << tre[u].r << ' ' << l << ' ' << r << endl;
		if(l<=mid) plu(ls(u),l,r,k);
		if(mid<r) plu(rs(u),l,r,k);
//		cout << "1919810" << endl;
		pushup(u);
	}
}

long long query(int u,int l,int r) {
	if(l<=tre[u].l&&r>=tre[u].r) return tre[u].sum%mod;
	pushdown(u);
	int mid=(tre[u].l+tre[u].r)/2;
	long long summ=0;
	if(l<=mid) summ+=query(ls(u),l,r);
	if(mid<r) summ+=query(rs(u),l,r);
	return summ;
}

void dfs1(int u,int f) {
//	if(u==0) return;
	fa[u]=f;
	size[u]=1;
	dep[u]=dep[f]+1;
	int mson=0;
	for(int i=first[u];i;i=arr[i].next) {
		if(arr[i].to==f) continue;
		dfs1(arr[i].to,u);
		size[u]+=size[arr[i].to];
		if(size[arr[i].to]>mson) {
			mson=size[arr[i].to];
			son[u]=arr[i].to;
		}
	}
}

int cnt;
void dfs2(int u,int f) {
	top[u]=f;
	dfn[u]=++cnt;
	plu(1,dfn[u],dfn[u],val[u]);
//	cout << "发NSF" << endl;
	if(son[u]==0) return;
	dfs2(son[u],f);
	for(int i=first[u];i;i=arr[i].next) {
		if(arr[i].to==son[u]||arr[i].to==fa[u]) continue;
		dfs2(arr[i].to,arr[i].to);
	}
}

void plus_path(int u,int v,int k) {
	while(top[u]!=top[v]) {
		if(dep[top[u]]<dep[top[v]]) swap(u,v);
		plu(1,dfn[top[u]],dfn[u],k);
		u=fa[top[u]];
	}
	if(dep[top[u]]>dep[top[v]]) swap(u,v);
	plu(1,dfn[u],dfn[v],k);
}

long long query_path(int u,int v) {
	long long summ=0;
	while(top[u]!=top[v]) {
		if(dep[top[u]]<dep[top[v]]) swap(u,v);
		summ+=query(1,dfn[top[u]],dfn[u]);
		summ%=mod;
		u=fa[top[u]];
	}
	if(dep[top[u]]>dep[top[v]]) swap(u,v);
	summ+=query(1,dfn[u],dfn[v]);
	summ%=mod;
	return summ;
}

void plus_tree(int u,int k) {
	plu(1,dfn[u],dfn[u]+size[u]-1,k);
}

long long query_tree(int u) {
	return query(1,dfn[u],dfn[u]+size[u]-1);
}

int main() {
	int x,y;
	cin >> n >> m >> r >> mod;
	for(int i=1;i<=n;++i) cin >> val[i];
	for(int i=1;i!=n;++i) {
		cin >> x >> y;
		add(x,y);
		add(y,x);
	}
	build(1,1,n);
	dfs1(r,0); //遍历到的节点,该节点的父亲节点
//	cout << "热i法国火热" << endl;
	dfs2(r,r); //遍历到的节点,该节点所在链的顶点
	
	int op,u,v,k;
	while(m--) {
		cin >> op;
		if(op==1) {
			cin >> u >> v >> k;
			plus_path(u,v,k);
		}else if(op==2) {
			cin >> u >> v;
			cout << query_path(u,v) << endl;
		}else if(op==3) {
			cin >> u >> k;
			plus_tree(u,k);
		}else {
			cin >> u;
			cout << query_tree(u) << endl;
		}
	}
	return 0;
}

2022/11/21 17:03
加载中...