唐式代码树链剖分
查看原帖
唐式代码树链剖分
820574
time_keeper楼主2024/8/12 21:45

违规紫衫

求调

线段树似乎没问题

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5 + 10;
int n,m,root,mod;
inline int ls(int x){
	return x << 1;
}
inline int rs(int x){
	return x << 1 | 1;
}
struct edge{
	int u,v;
}e[N];
int h[N],tot = 1;
int val[N];
inline void add(int u,int v){
	e[++tot].u = h[u],e[tot].v = v,h[u] = tot;
}
int fa[N],dep[N],son[N],sz[N],top[N],dfn[N],cnt = 0,rk[N];
void dfs1(int p,int f){
	sz[p] = 1,dep[p] = dep[f] + 1;
	fa[p] = f;
	for(int i = h[p];i;i = e[i].u){
		int v = e[i].v;
		if(v == f) continue; 
		dfs1(v,p);
		sz[p] += sz[v];
		if(sz[v] > sz[son[p]]) son[p] = v;
	}
}
void dfs2(int p,int f){
//	printf("p=%d f=%d\n",p,f);
	top[p] = f;
	dfn[p] = ++cnt;
	rk[cnt] = p;
	if(!son[p]) return;
	dfs2(son[p],f);
	for(int i = h[p];i;i = e[i].u){
		int v = e[i].v;
		if(v != son[p] && v != fa[p]) dfs2(v,v);
	}
}
struct node{
	int data;
	int l,r;
	int lazytag;
}tree[N << 2];
inline void pushup(int p){
	tree[p].data = (tree[ls(p)].data + tree[rs(p)].data) % mod;
}
void build(int p,int l,int r){
	tree[p].l = l;
	tree[p].r = r;
	if(l == r){
		tree[p].data = val[rk[l]];
		return;
	}
	int mid = (l + r) >> 1;
	build(ls(p),l,mid);
	build(rs(p),mid+1,r);
	tree[p].data = tree[ls(p)].data + tree[rs(p)].data;
}
void pushdown(int p){
	tree[ls(p)].lazytag += tree[p].lazytag;
	tree[ls(p)].data += (tree[ls(p)].r - tree[ls(p)].l + 1) * tree[p].lazytag;
	tree[rs(p)].lazytag += tree[p].lazytag;
	tree[rs(p)].data += (tree[rs(p)].r - tree[rs(p)].l + 1) * tree[p].lazytag;
	tree[p].lazytag = 0;
}
void change(int p,int l,int r,int x){
	if(tree[p].l > r || tree[p].r < l){
		return;
	}
	if(tree[p].l >= l && tree[p].r <= r){
		tree[p].lazytag += x;
		tree[p].data += (tree[p].r - tree[p].l + 1) * x;
		return; 
	}
	if(tree[p].lazytag > 0){
		pushdown(p);
	}
	change(ls(p),l,r,x);
	change(rs(p),l,r,x);
	tree[p].data = tree[ls(p)].data + tree[rs(p)].data; 
}
int query(int p,int l,int r){
	if(tree[p].l > r || tree[p].r < l) return 0;
	if(tree[p].l >= l && tree[p].r <= r) return tree[p].data;
	if(tree[p].lazytag > 0) pushdown(p);
	return query(ls(p),l,r) + query(rs(p),l,r);
}
int sum(int x,int y){
	int ans = 0;
	while(top[x] != top[y]){
		if(dep[top[x]] < dep[top[y]]) swap(x,y);
		ans = (ans + query(1,dfn[top[x]],dfn[x])) % mod;
		x = fa[top[x]];
	}
	if(dfn[x] > dfn[y]) swap(x,y);
	return (ans + query(1,dfn[x],dfn[y])) % mod;
}
void update(int x,int y,int k){
	while(top[x] != top[y]){
		if(dep[top[x]] < dep[top[y]]) swap(x,y);
		change(1,dfn[top[x]],dfn[x],k);
		x = fa[top[x]];
	}
	if(dfn[x] > dfn[y]) swap(x,y);
	change(1,dfn[x],dfn[y],k);
}
//void Debug(int k){
//	for(int i = 1;i <= n - 1;i++){
//		cout << i << "_" << tree[i].data << "_" << tree[i].tag << "_" << k << " " << ls(i) << "_" << tree[ls(i)].data << "_" << tree[i].tag << "_" << k << "\n";
//		cout << i << "_" << tree[i].data << "_" << tree[i].tag << "_" << k << " " << rs(i) << "_" << tree[rs(i)].data << "_" << tree[i].tag << "_" << k << "\n";
//	} 
//}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(nullptr),cout.tie(nullptr);
	cin >> n >> m >> root >> mod;
	for(int i = 1;i <= n;i++) cin >> val[i];
	for(int i = 1;i < m;i++){
		int u,v;cin >> u >> v;
		add(u,v),add(v,u);
	}
	
	dfs1(root,0);dfs2(root,root);
//	for(int i = 1;i <= n;i++){
//		cout << dfn[i] << " " << dep[i] << " " << son[i] << " " << rk[i] << " " << top[i] << '\n'; 
//	}
	build(1,1,n);
	for(int i = 1;i <= m;i++){
		int opt;
		cin >> opt;
		if(opt == 1){
			int x,y,z;
			cin >> x >> y >> z;update(x,y,z);
		}else if(opt == 2){
			int x,y;
			cin >> x >> y;
			cout << sum(x,y) % mod<< '\n';
		}else if(opt == 3){
			int x,y;
			cin >> x >> y;
			change(1,dfn[x],dfn[x] + sz[x] - 1,y);
		}else if(opt == 4){
			int x;
			cin >> x;
			cout << query(1,dfn[x],dfn[x] + sz[x] - 1) % mod << '\n';
		}
//		Debug(i);
	}
	
}
2024/8/12 21:45
加载中...