悬3关 在线求调,挺急的
查看原帖
悬3关 在线求调,挺急的
839183
i__ak_io楼主2024/9/12 08:11
#include <iostream>
#include <cstdio>

using namespace std;

#define lnode(x) x<<1
#define rnode(x) x<<1|1
#define int long long
const int N=1e6+5;

struct Tree {int val,tag,lid,rid;} tree[N<<4];
struct Edge {int val,beg,nex;} edge[N<<2];
struct Point {int son,father,siz,deep,top,id;} point[N];

int n,m,r,p,op;
int tot=0,index=0;
int in[N],in_new[N];

void addedge (int x,int y) {
	edge[++tot].val=y;
	edge[tot].nex=edge[x].beg;
	edge[x].beg=tot;
}

void dfs_first (int node,int fa) {
	point[node].deep=point[fa].deep+1;
	point[node].father=fa;
	point[node].siz=1;
	for (int i=edge[node].beg;i;i=edge[i].nex) {
		int k=edge[i].val;
		if (k==fa) continue;
		dfs_first(k,node);
		point[node].siz+=point[k].siz;
		if (point[point[node].son].siz<point[k].siz) point[node].son=k;
	}
}

void dfs_second (int node,int top) {
	point[node].id=++index;
	in_new[index]=in[node];
	point[node].top=top;
	if (!point[node].son) return ;
	dfs_second(point[node].son,top);
	for (int i=edge[node].beg;i;i=edge[node].nex) {
		int k=edge[node].val;
		if (k==point[node].father||k==point[node].son) continue;
		dfs_second(k,k);
	}
}

void push_up (int node) {
	tree[node].val=(tree[lnode(node)].val+tree[rnode(node)].val)%p;
}

void push_down (int node) {
	int mid=tree[node].lid+tree[node].rid>>1;
	tree[lnode(node)].tag+=tree[node].tag;
	tree[lnode(node)].tag%=p;
	tree[lnode(node)].val+=tree[node].tag*(mid-tree[node].lid+1);
	tree[lnode(node)].val%=p;
	tree[rnode(node)].tag+=tree[node].tag;
	tree[rnode(node)].tag%=p;
	tree[rnode(node)].val+=tree[node].tag*(tree[node].rid-mid);
	tree[rnode(node)].val%=p;
	tree[node].tag=0;
}

void build (int node,int l,int r) {
	tree[node].tag=0;
	tree[node].lid=l,tree[node].rid=r;
	if (l==r) {
		tree[node].val=in_new[l]%p;
		return ;
	}
	int mid=l+r>>1;
	build(lnode(node),l,mid);
	build(rnode(node),mid+1,r);
	push_up(node);
}

void update (int node,int l,int r,int change) {
	if (l<=tree[node].lid&&tree[node].rid<=r) {
		tree[node].tag+=change;
		tree[node].val+=change*(tree[node].rid-tree[node].lid+1);
		tree[node].val%=p;
		return ;
	}
	push_down(node);
	int mid=tree[node].lid+tree[node].rid>>1;
	if (l<=mid) update(lnode(node),l,r,change);
	if (r>mid) update(rnode(node),l,r,change);
	push_up(node);
}

int query (int node,int l,int r) {
	if (l<=tree[node].lid&&tree[node].rid<=r) return tree[node].val%=p;
	push_down(node);
	int res=0,mid=tree[node].lid+tree[node].rid>>1;
	if (l<=mid) res=(res+query(lnode(node),l,r))%p;
	if (r>mid) res=(res+query(rnode(node),l,r))%p;
	return res%p;
}

void update_range (int x,int y,int z) {
	while (point[x].top!=point[y].top) {
		if (point[point[x].top].deep<point[point[y].top].deep) swap(x,y);
		update(1,point[point[x].top].id,point[x].id,z);
		x=point[point[x].top].father;
	}
	if (point[x].deep>point[y].deep) swap(x,y);
	update(1,point[x].id,point[y].id,z);
}

int query_range (int x,int y) {
	int res=0;
	while (point[x].top!=point[y].top) {
		if (point[point[x].top].deep<point[point[y].top].deep) swap(x,y);
		res+=query(1,point[point[x].top].id,point[x].id);
		res%=p;
		x=point[point[x].top].father;
	}
	if (point[x].deep>point[y].deep) swap(x,y);
	res=(res+query(1,point[x].id,point[y].id))%p;
	return res%p;
}

void update_tree (int x,int z) {
	update(1,point[x].id,point[x].id+point[x].siz-1,z);
}

int query_tree (int x) {
	return query(1,point[x].id,point[x].id+point[x].siz-1)%p;
}

signed main (void) {
	scanf("%lld %lld %lld %lld",&n,&m,&r,&p);
	for (int i=1;i<=n;++i)
		scanf("%lld",&in[i]);
	int x,y,z;
	for (int i=1;i<n;++i){
		scanf("%lld %lld",&x,&y);
		addedge(x,y),addedge(y,x);
	}
	dfs_first(r,0);
	dfs_second(r,r);
	build(1,1,n);
	for (int i=1;i<=m;++i) {
		scanf("%lld",&op);
		if (op==1) {
			scanf("%lld %lld %lld",&x,&y,&z);
			update_range(x,y,z);
		} else if (op==2) {
			scanf("%lld %lld",&x,&y);
			printf("%lld\n",query_range(x,y));
		} else if (op==3) {
			scanf("%lld %lld",&x,&z);
			update_tree(x,z);
		} else {
			scanf("%lld",&x);
			printf("%lld\n",query_tree(x));
		}
	}
	return 0;
}
2024/9/12 08:11
加载中...