zoukankan      html  css  js  c++  java
  • 【模板】树链剖分

    好久不写树剖了,昨天刚好xry提起,今天洛谷智推又有这题....于是就想写一写.....然后果然出现了很多很多的错误2333

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN = 200010;
    int n, m, r, mod, x, y, z, k;
    int num, from[MAXN], next[MAXN], to[MAXN], w[MAXN];
    int w1[MAXN], a[MAXN << 2], lazy[MAXN << 2];
    int son[MAXN], id[MAXN], father[MAXN];
    int cnt;
    int depth[MAXN];
    int size[MAXN], top[MAXN];
    int res;
    inline int read() {
        char ch; bool f = false; int res = 0;
        while (((ch = getchar()) < '0' || ch > '9') && ch != '-');
        if (ch == '-') f = true; else res = ch - '0';
        while ((ch = getchar()) >= '0' && ch <= '9') res = (res << 3) + (res << 1) + ch - '0';
        return f? ~res + 1 : res;
    }
    inline void add(int x, int y) { // build tree
    	to[++ num] = y, next[num] = from[x], from[x] = num;
    	to[++ num] = x, next[num] = from[y], from[y] = num;
    }
    void dfs1(int x, int fa, int deep) {
    	depth[x] = deep;
    	father[x] = fa;
    	size[x] = 1;
    	int maxx = -1; // son 's max
    	for (int i = from[x]; i; i = next[i]) {
    		int y = to[i];
    		if (y == fa) // father
    			continue;
    		dfs1(y, x, deep + 1);
    		size[x] += size[y];
    		if (size[y] > maxx) {
    			son[x] = y;
    			maxx =  size[y];
    		}
    	}
    }
    void dfs2(int x, int Top) { // tree link top
    	id[x] = ++ cnt; // new number
    	w1[cnt] = w[x]; // new value
    	top[x] = Top;
    	if (! son[x]) // no son
    		return;
    	dfs2(son[x], Top);
    	for (int i = from[x]; i; i = next[i]) {
    		int y = to[i];
    		if (y == father[x] || y == son[x])
    			continue;
    		dfs2(y, y); // light son -> link top
    	}
    }
    //segment tree
    inline void pushdown(int x, int y) {
    	int t = x << 1, w = x << 1 | 1, z = y >> 1;
    	lazy[t] += lazy[x], lazy[w] += lazy[x];
    	a[t] += lazy[x] * (y - z), a[w] += lazy[x] * z;
    	a[t] %= mod, a[w] %= mod, lazy[x] = 0;
    }
    void build (int x, int t, int w) {
    	if (t == w) {
    		a[x] = w1[t];
    		if (a[x] > mod)
    			a[x] %= mod;
    		return;
    	}
    	build(x << 1, t, t + w >> 1); // left son
    	build(x << 1 | 1, (t + w >> 1) + 1, w); // right son
    	a[x] = (a[x << 1] + a[x << 1 | 1] % mod);
    }
    void query(int x, int l, int r, int t, int w) {
    	if (t <= l && w >= r) {
    		res = (res + a[x]) % mod;
    		return;
    	}
    	else {
    		int mid = l + r >> 1;
    		if (lazy[x])
    			pushdown(x, r - l + 1);
    		if (t <= mid)
    			query(x << 1, l, mid, t, w);
    		if (w > mid)
    			query(x << 1 | 1, mid + 1, r, t, w);
    	}
    }
    void update(int x, int l, int r, int t, int w, int k) {
    	if (t <= l && w >= r)
    		lazy[x] += k, a[x] += k * (r - l + 1);
    	else {
    		int mid = l + r >> 1;
    		if (lazy[x])
    			pushdown(x, r - l + 1);
    		if (t <= mid)
    			update(x << 1, l, mid, t, w, k);
    		if (w > mid)
    			update(x << 1 | 1, mid + 1, r, t, w, k);
    		a[x] = (a[x << 1] + a[x << 1 | 1]) % mod;
    	}
    }
    //
    inline void addroad(int x, int y, int k) {
    	k %= mod;
    	while (top[x] != top[y]) { 
    		if (depth[top[x]] < depth[top[y]])
    			swap(x, y);
    		update(1, 1, n, id[top[x]], id[x], k);
    		x = father[top[x]];
    	}
    	if (depth[x] > depth[y])
    		swap(x, y);
    	update(1, 1, n, id[x], id[y], k);
    }
    inline int sumroad(int x, int y) {
    	int ans = 0;
    	while (top[x] != top[y]) {
    		if (depth[top[x]] < depth[top[y]])
    			swap(x, y);
    		res = 0;
    		query(1, 1, n, id[top[x]], id[x]);
    		ans = (ans + res) % mod;
    		x = father[top[x]];
    	}
    	if (depth[x] > depth[y])
    		swap(x, y);
    	res = 0;
    	query(1, 1, n, id[x], id[y]);
    	ans = ans + res;
    	return ans % mod;
    }
    inline int sumson(int x) {
    	res = 0;
    	query(1, 1, n, id[x], id[x] + size[x] - 1);
    	return res;
    }
    inline void addson(int x,int k) {
    	update(1, 1, n, id[x], id[x] + size[x] - 1, k);
    }
    int main() {
    	n = read(), m = read(), r = read(), mod = read();
    	for (int i = 1; i <= n; i ++)
    		w[i]=read();
    	for (int i = 1; i < n; i ++)
    		add(read(), read());
    	dfs1(r, 0, 1);
    	dfs2(r, r);
    	build(1, 1, n);
    	while (m --) {
    		k = read(), x = read();
    		if (k == 1) {
    			y = read(), z=read();
    			addroad(x, y, z);
    		}
    		else if (k == 2) {
    			y = read();
    			printf("%d
    ", sumroad(x, y));
    		}
    		else if (k == 3) {
    			y = read();
    			addson(x, y);
    		}
    		else printf("%d
    ", sumson(x));
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    [computer graphics]世界坐标系->相机坐标系详细推导
    [Computer Vision]霍夫变换直线检测
    [OpenGL](翻译+补充)投影矩阵的推导
    [WebGL]二维变换
    [WebGL]Shader中的数据和简单的工作流
    图像梯度
    皮肤镜图片毛发去除
    胸部CT提取分割肺部
    医学影像重采样
    ES7学习笔记(十二)高亮 和 搜索建议
  • 原文地址:https://www.cnblogs.com/wjnclln/p/10570031.html
Copyright © 2011-2022 走看看