<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      例題:https://www.luogu.com.cn/problem/P3384

      已知一棵包含 \(n\) 個結點的樹(連通且無環),每個節點上包含一個數值,需要支持以下操作:
      1 x y z:表示將樹從 \(x\)\(y\) 結點最短路徑上所有節點的值都加上 \(z\)
      2 x y:表示求樹從 \(x\)\(y\) 結點最短路徑上所有節點的值之和。
      3 x z:表示將以 \(x\) 為根節點的子樹內所有節點值都加上 \(z\)
      4 x:表示求以 \(x\) 為根節點的子樹內所有節點值之和

      #include<bits/stdc++.h>
      using namespace std;
      using LL = long long;
      struct HLD{
      	vector<vector<int>> e;
      	vector<int> top, dep, parent, siz, son, id, a, val;
      	int idx, mod;
      	HLD(int n, int P){
      		mod = P;
      		e.resize(n + 1);
      		top.resize(n + 1);
      		dep.resize(n + 1);
      		parent.resize(n + 1);
      		siz.resize(n + 1);
      		son.resize(n + 1);
      		id.resize(n + 1);
      		idx = 0;
      		a.resize(n + 1);
      		val.resize(n + 1);
      		tr.resize((n << 2) + 1);
      	}
      	void add(int u, int v){
      		e[u].push_back(v);
      		e[v].push_back(u);
      	}
      	void dfs1(int u){
      		siz[u] = 1;
      		dep[u] = dep[parent[u]] + 1;
      		for (auto v : e[u]){
      			if (v == parent[u]) continue;
      			parent[v] = u;
      			dfs1(v);
      			siz[u] += siz[v];
      			if (siz[v] > siz[son[u]]) son[u] = v;
      		}
      	}
      	void dfs2(int u, int up){
      		id[u] = ++ idx;
      		top[u] = up;
      		val[idx] = a[u];
      		if (son[u]) dfs2(son[u], up);
      		for (auto v : e[u]){
      			if (v == parent[u] || v == son[u]) continue;
      			dfs2(v, v);
      		}
      	}
      	
      	struct node{
      		int l, r;
      		LL sum, add;
      	};
      	vector<node> tr;
      	void pushup(int u){
      		tr[u].sum = (tr[u << 1].sum + tr[u << 1 | 1].sum) % mod;
      	}
      	void pushdown(int u){
      		auto &root = tr[u], &left = tr[u << 1], &right = tr[u << 1 | 1];
      		left.add = (left.add + root.add) % mod;
      		left.sum = (left.sum + root.add * (left.r - left.l + 1) % mod) % mod;
      		right.add = (right.add + root.add) % mod;
      		right.sum = (right.sum + root.add * (right.r - right.l + 1) % mod) % mod;
      		root.add = 0;
      	}
      	void build(int u, int l, int r){
      		if (l == r){
      			tr[u] = {l, r, val[r], 0};
      			return;
      		}
      		tr[u] = {l, r};
      		int mid = l + r >> 1;
      		build(u << 1, l, mid);
      		build(u << 1 | 1, mid + 1, r);
      		pushup(u);
      	}
      	void modify(int u, int l, int r, LL k){
      		if (tr[u].l >= l && tr[u].r <= r){
      			tr[u].sum = (tr[u].sum + k * (tr[u].r - tr[u].l + 1) % mod) % mod;
      			tr[u].add = (tr[u].add + k) % mod;
      		}
      		else {
      			pushdown(u);
      			int mid = tr[u].l + tr[u].r >> 1;
      			if (l <= mid) modify(u << 1, l, r, k);
      			if (r > mid) modify(u << 1 | 1, l, r, k);
      			pushup(u);
      		}
      	}
      	LL query(int u, int l, int r){
      		if (tr[u].l >= l && tr[u].r <= r) return tr[u].sum;
      		pushdown(u);
      		int mid = tr[u].l + tr[u].r >> 1;
      		LL sum = 0;
      		if (l <= mid) sum = query(u << 1, l, r);
      		if (r > mid) sum = (sum + query(u << 1 | 1, l, r)) % mod;
      		return sum;
      	}
      	
      	void modifyRange(int u, int v, int k){
      		while(top[u] != top[v]){
      			if (dep[top[u]] < dep[top[v]]) swap(u, v);
      			modify(1, id[top[u]], id[u], k);
      			u = parent[top[u]];
      		}
      		if (dep[u] > dep[v]) swap(u, v);
      		modify(1, id[u], id[v], k);
      	}
      	LL queryRange(LL u, LL v){
      		LL ans = 0;
      		while(top[u] != top[v]){
      			if (dep[top[u]] < dep[top[v]]) swap(u, v);
      			ans = (ans + query(1, id[top[u]], id[u])) % mod;
      			u = parent[top[u]];
      		}
      		if (dep[u] > dep[v]) swap(u, v);
      		return (ans + query(1, id[u], id[v])) % mod;
      	}
      	void modifySon(LL u, LL k){
      		modify(1, id[u], id[u] + siz[u] - 1, k);
      	}
      	LL querySon(LL u){
      		return query(1, id[u], id[u] + siz[u] - 1) % mod;
      	}
      };
      int main(){
      	ios::sync_with_stdio(false);cin.tie(0);
      	int n, m, r, p;
      	cin >> n >> m >> r >> p;
      	HLD t(n, p);
      	for (int i = 1; i <= n; i ++ ){
      		cin >> t.a[i];
      	}
      	for (int i = 0; i < n - 1; i ++ ){
      		int u, v;
      		cin >> u >> v;
      		t.add(u, v);
      	}
      	t.dfs1(r);
      	t.dfs2(r, r);
      	t.build(1, 1, n);
      	
      	while (m -- ){
      		int op, x, y, z;
      		cin >> op >> x;
      		if (op == 1){
      			cin >> y >> z;
      			t.modifyRange(x, y, z);
      		}
      		else if (op == 2){
      			cin >> y;
      			cout << t.queryRange(x, y) << "\n";
      		}
      		else if (op == 3){
      			cin >> z;
      			t.modifySon(x, z);
      		}
      		else{
      			cout << t.querySon(x) << "\n";
      		}
      	}
      	return 0;
      }
      
      posted on 2022-08-28 16:55  Hamine  閱讀(59)  評論(0)    收藏  舉報

      主站蜘蛛池模板: 亚洲人成色77777| 国产精品黄色一区二区三区| 亚洲国产一区二区在线| 国产在线精品无码二区| 高清无码爆乳潮喷在线观看| 国产丰满乱子伦无码专区| 美女18禁一区二区三区视频| 亚洲一区二区中文av| 成人永久免费A∨一级在线播放 | 暖暖 在线 日本 免费 中文| 91网站在线看| 免费无码久久成人网站入口| 人妻少妇偷人精品一区| 97久久综合亚洲色hezyo| 亚洲中文字幕无码一久久区| 性欧美乱熟妇xxxx白浆| 国产一区二区三区九九视频| 在线高清免费不卡全码| 久久精品国产亚洲av麻豆软件| 亚洲精品一区二区三区大| 无码va在线观看| 中文字幕一区二区人妻电影| 亚洲AV天天做在线观看| 亚洲一区二区精品极品| 国产伦精区二区三区视频| 狠狠v日韩v欧美v| 午夜射精日本三级| 久久久国产精品樱花网站| 亚洲av不卡电影在线网址最新| 一区二区三区四区黄色片| 国产欧美一区二区三区免费视频| 国产精品不卡一区二区三区| 亚洲综合无码明星蕉在线视频| 欧美成人黄在线观看| 午夜大片免费男女爽爽影院| 日韩国产中文字幕精品| 九九热在线视频只有精品| 康定县| 国产精品午夜福利在线观看| 国产香蕉一区二区三区在线视频| 午夜在线观看成人av|