• 树链剖分之重链剖分 模板


    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define N 100010
    #define ll long long
    int P;
    int a[N];
    int last[N], nxt[N * 2], to[N * 2], len = 0;
    int si[N], hv[N], fa[N], dp[N], dfn[N], tp[N];
    ll f[N * 4], bz[N * 4];
    void add(int x, int y) {
    	to[++len] = y;
    	nxt[len] = last[x];
    	last[x] = len;
    }
    void dfs0(int k) {
    	si[k] = 1, dp[k] = dp[fa[k]] + 1;
    	for(int i = last[k]; i; i = nxt[i]) if(to[i] != fa[k]) {
    		fa[to[i]] = k;
    		dfs0(to[i]);
    		si[k] += si[to[i]];
    		if(si[to[i]] > si[hv[k]]) hv[k] = to[i];
    	}
    }
    void dfs(int k, int rt) {
    	dfn[k] = ++dfn[0];
    	tp[k] = rt;
    	if(hv[k]) dfs(hv[k], rt);
    	for(int i = last[k]; i; i = nxt[i]) if(to[i] != fa[k] && to[i] != hv[k]) dfs(to[i], to[i]);
    }
    void down(int v, int l, int r, int mid) {
    	f[v * 2] = (f[v * 2] + bz[v] * (mid - l + 1)) % P;
    	f[v * 2 + 1] = (f[v * 2 + 1] + bz[v] * (r - mid)) % P;
    	bz[v * 2] = (bz[v * 2] + bz[v]) % P;
    	bz[v * 2 + 1] = (bz[v * 2 + 1] + bz[v]) % P;
    	bz[v] = 0;
    }
    void ins(int v, int l, int r, int x, int y, ll c) {
    	if(x <= l && r <= y) {
    		f[v] = (f[v] + c * (r - l + 1)) % P;
    		bz[v] = (bz[v] + c) % P;
    	}
    	else {
    		int mid = (l + r) / 2;
    		down(v, l, r, mid);
    		if(x <= mid) ins(v * 2, l, mid, x, y, c);
    		if(y > mid) ins(v * 2 + 1, mid + 1, r, x, y, c);
    		f[v] = (f[v * 2] + f[v * 2 + 1]) % P;
    	}
    }
    ll find(int v, int l, int r, int x, int y) {
    	if(x <= l && r <= y) return f[v];
    	int mid = (l + r) / 2;
    	down(v, l, r, mid);
    	ll s = 0;
    	if(x <= mid) s = (s + find(v * 2, l, mid, x, y)) % P;
    	if(y > mid) s = (s + find(v * 2 + 1, mid + 1, r, x, y)) % P;
    	f[v] = (f[v * 2] + f[v * 2 + 1]) % P;
    	return s;
    }
    int main() {
    	int n, Q, rt, i, x, y, z, op;
    	scanf("%d%d%d%d", &n, &Q, &rt, &P);
    	for(i = 1; i <= n; i++) scanf("%d", &a[i]);
    	for(i = 1; i < n; i++) {
    		scanf("%d%d", &x, &y);
    		add(x, y), add(y, x);
    	}
    	dfs0(rt);
    	dfs(rt, rt);
    	for(i = 1; i <= n; i++) ins(1, 1, n, dfn[i], dfn[i], a[i]);
    	while(Q--) {
    		scanf("%d", &op);
    		if(op == 1) {
    			scanf("%d%d%d", &x, &y, &z);
    			int f1 = tp[x], f2 = tp[y];
    			while(f1 != f2) {
    				if(dp[f1] < dp[f2]) swap(x, y), swap(f1, f2);
    				ins(1, 1, n, dfn[f1], dfn[x], z);
    				x = fa[f1], f1 = tp[x];
    			}
    			if(dp[x] < dp[y]) swap(x, y);
    			ins(1, 1, n, dfn[y], dfn[x], z);
    		}
    		else if(op == 2) {
    			scanf("%d%d%", &x, &y);
    			ll ans = 0;
    			int f1 = tp[x], f2 = tp[y];
    			while(f1 != f2) {
    				if(dp[f1] < dp[f2]) swap(x, y), swap(f1, f2);
    				ans = (ans + find(1, 1, n, dfn[f1], dfn[x])) % P;
    				x = fa[f1], f1 = tp[x];
    			}
    			if(dp[x] < dp[y]) swap(x, y);
    			ans = (ans + find(1, 1, n, dfn[y], dfn[x])) % P;
    			printf("%lld
    ", ans);
    		}
    		else if(op == 3) {
    			scanf("%d%d", &x, &z);
    			ins(1, 1, n, dfn[x], dfn[x] + si[x] - 1, z);
    		}
    		else {
    			scanf("%d", &x);
    			printf("%lld
    ", find(1, 1, n, dfn[x], dfn[x] + si[x] - 1));
    		}
    	}
    	return 0;
    }
    
    哈哈哈哈哈哈哈哈哈哈
  • 相关阅读:
    Oracle存储过程
    Oracle触发器
    Oracle伪列
    Oracle索引
    Oracle视图
    Oracle数据库链路
    异常处理之动手动脑
    四则运算自动出题之javaweb版
    继承与多态之动手动脑
    javaweb之添加学生信息
  • 原文地址:https://www.cnblogs.com/LZA119/p/14623418.html
Copyright © 2020-2023  润新知