• [洛谷P3833][SHOI2012]魔法树


    题目大意:给一棵树,路径加,子树求和

    题解:树剖

    卡点:

    C++ Code:

    #include <cstdio>
    #include <iostream>
    #define maxn 100010
    
    int head[maxn], cnt;
    struct Edge {
    	int to, nxt;
    } e[maxn << 1];
    inline void add(int a, int b) {
    	e[++cnt] = (Edge) {b, head[a]}; head[a] = cnt;
    }
    
    int n, m;
    
    namespace SgT {
    	long long V[maxn << 2], tg[maxn << 2];
    	int L, R, num;
    
    	inline void pushdown(int rt, int len) {
    		long long &__tg = tg[rt];
    		V[rt << 1] += __tg * (len + 1 >> 1);
    		V[rt << 1 | 1] += __tg * (len >> 1);
    		tg[rt << 1] += __tg;
    		tg[rt << 1 | 1] += __tg;
    		__tg = 0;
    	}
    	void __add(int rt, int l, int r) {
    		if (L <= l && R >= r) {
    			V[rt] += static_cast<long long> (r - l + 1) * num;
    			tg[rt] += num;
    			return ;
    		}
    		int mid = l + r >> 1;
    		if (tg[rt]) pushdown(rt, r - l + 1);
    		if (L <= mid) __add(rt << 1, l, mid);
    		if (R > mid) __add(rt << 1 | 1, mid + 1, r);
    		V[rt] = V[rt << 1] + V[rt << 1 | 1];
    	}
    	void add(int __L, int __R, int __num) {
    		L = __L, R = __R, num = __num;
    		__add(1, 1, n);
    	}
    
    	long long __ask(int rt, int l, int r) {
    		if (L <= l && R >= r) return V[rt];
    		int mid = l + r >> 1;
    		long long ans = 0;
    		if (tg[rt]) pushdown(rt, r - l + 1);
    		if (L <= mid) ans = __ask(rt << 1, l, mid);
    		if (R > mid) ans += __ask(rt << 1 | 1, mid + 1, r);
    		return ans;
    	}
    	long long ask(int __L, int __R) {
    		L = __L, R = __R;
    		return __ask(1, 1, n);
    	}
    }
    using SgT::add;
    using SgT::ask;
    
    int fa[maxn], dep[maxn], sz[maxn];
    int dfn[maxn], idx, top[maxn], son[maxn];
    void dfs1(int u) {
    	sz[u] = 1;
    	for (int i = head[u]; i; i = e[i].nxt) {
    		int v = e[i].to;
    		if (v != fa[u]) {
    			fa[v] = u;
    			dep[v] = dep[u] + 1;
    			dfs1(v);
    			sz[u] += sz[v];
    			if (!son[u] || sz[v] > sz[son[u]]) son[u] = v;
    		}
    	}
    }
    void dfs2(int u) {
    	dfn[u] = ++idx;
    	int v = son[u];
    	if (v) top[v] = top[u], dfs2(v);
    	for (int i = head[u]; i; i = e[i].nxt) {
    		v = e[i].to;
    		if (v != fa[u] && v != son[u]) {
    			top[v] = v;
    			dfs2(v);
    		}
    	}
    }
    
    void modify(int x, int y, int z) {
    	while (top[x] != top[y]) {
    		if (dep[top[x]] < dep[top[y]]) std::swap(x, y);
    		add(dfn[top[x]], dfn[x], z);
    		x = fa[top[x]];
    	}
    	if (dep[x] > dep[y]) std::swap(x, y);
    	add(dfn[x], dfn[y], z);
    }
    long long query(int x) {
    	return ask(dfn[x], dfn[x] + sz[x] - 1);
    }
    int main() {
    	std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
    	std::cin >> n;
    	for (int i = 1, a, b; i < n; i++) {
    		std::cin >> a >> b; a++, b++;
    		add(a, b);
    		add(b, a);
    	}
    	dfs1(1);
    	top[1] = 1;
    	dfs2(1);
    	std::cin >> m;
    	while (m --> 0) {
    		char op;
    		int x, y, z;
    		std::cin >> op >> x; x++;
    		if (op == 'A') {
    			std::cin >> y >> z; y++;
    			modify(x, y, z);
    		} else std::cout << query(x) << '
    ';
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    ES5数组扩展
    ES5给object扩展的一些静态方法
    poj2531-dfs
    快排
    阶段性总结-贪心算法
    日常算法题
    poj1979 解题报告
    poj 2586
    poj3069
    poj2709 解题报告
  • 原文地址:https://www.cnblogs.com/Memory-of-winter/p/10000015.html
Copyright © 2020-2023  润新知