zoukankan      html  css  js  c++  java
  • 洛谷 P3178 [HAOI2015]树上操作

    Description

    洛谷传送门

    Solution

    树链剖分

    树链剖分板子题,比板子还板子

    关于树链剖分我就不多说了,如果有的话可以看我的博客 浅谈树链剖分

    回归正题,我们发现题目只要求单点加,子树加,以及查询一点到根节点路径和。

    单点加不就是区间加把左右端点改成那个点吗?

    子树加不就是板子吗??

    查询一点到根节点路径和不就是路径查询简化版吗???

    综上所述,这道题是板子的板子

    那么我们这道题就已经做完了,只需要把板子里多余的函数删掉就好啦。

    别忘了开 (long long)

    Code

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    
    #define ll long long
    #define N 500010
    #define ls rt << 1
    #define rs rt << 1 | 1
    #define INF 0x3f3f3f3f
    
    using namespace std;
    
    struct node{
    	ll v, nxt;
    }edge[N << 1];
    ll head[N], tot;
    ll n, m;
    ll w[N], tw[N];
    ll dep[N], siz[N], fa[N], son[N];
    ll top[N], id[N], cnt;
    ll a[N << 2], lazy[N << 2];
    
    inline ll read(){
    	ll x = 0, f = 1;
    	char ch = getchar();
    	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
    	while(ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    	return f * x;
    }
    
    inline void add(ll x, ll y){
    	edge[++tot] = (node){y, head[x]};
    	head[x] = tot;
    }
    
    void dfs1(ll x, ll f){
    	fa[x] = f;
    	dep[x] = dep[f] + 1;
    	siz[x] = 1;
    	for(ll i = head[x]; i; i = edge[i].nxt){
    		ll y = edge[i].v;
    		if(y == f) continue;
    		dfs1(y, x);
    		siz[x] += siz[y];
    		if(!son[x] || siz[y] > siz[son[x]])
    			son[x] = y;
    	}
    }
    
    void dfs2(ll x, ll topfa){
    	top[x] = topfa;
    	id[x] = ++cnt;
    	tw[cnt] = w[x];
    	if(!son[x]) return;
    	dfs2(son[x], topfa);
    	for(ll i = head[x]; i; i = edge[i].nxt){
    		ll y = edge[i].v;
    		if(y == fa[x] || y == son[x]) continue;
    		dfs2(y, y);
    	}
    }
    
    inline void pushup(ll rt){
    	a[rt] = a[ls] + a[rs];
    }
    
    inline void pushdown(ll l, ll r, ll rt){
    	if(lazy[rt]){
    		ll mid = (l + r) >> 1;
    		a[ls] += lazy[rt] * (mid - l + 1);
    		a[rs] += lazy[rt] * (r - mid);
    		lazy[ls] += lazy[rt];
    		lazy[rs] += lazy[rt];
    		lazy[rt] = 0;
    	}
    }
    
    void build(ll l, ll r, ll rt){
    	if(l == r){
    		a[rt] = tw[l];
    		return;
    	}
    	ll mid = (l + r) >> 1;
    	build(l, mid, ls);
    	build(mid + 1, r, rs);
    	pushup(rt);
    }
    
    void update(ll L, ll R, ll k, ll l, ll r, ll rt){
    	if(L <= l && r <= R){
    		a[rt] += k * (r - l + 1);
    		lazy[rt] += k;
    		return;
    	}
    	pushdown(l, r, rt);
    	ll mid = (l + r) >> 1;
    	if(L <= mid) update(L, R, k, l, mid, ls);
    	if(R > mid) update(L, R, k, mid + 1, r, rs);
    	pushup(rt);
    }
    
    ll query(ll L, ll R, ll l, ll r, ll rt){
    	if(L <= l && r <= R)
    		return a[rt];
    	pushdown(l, r, rt);
    	ll mid = (l + r) >> 1;
    	ll res = 0;
    	if(L <= mid) res += query(L, R, l, mid, ls);
    	if(R > mid) res += query(L, R, mid + 1, r, rs);
    	return res;
    }
    
    void update_Son(ll x, ll k){
    	update(id[x], id[x] + siz[x] - 1, k ,1, n, 1);
    }
    
    ll query_Range(ll x, ll y){
    	ll res = 0;
    	while(top[x] != top[y]){
    		if(dep[top[x]] < dep[top[y]]) swap(x, y);
    		res += query(id[top[x]], id[x], 1, n, 1);
    		x = fa[top[x]];
    	}
    	if(dep[x] > dep[y]) swap(x, y);
    	res += query(id[x], id[y], 1, n, 1);
    	return res;
    }
    
    signed main(){
    	n = read(), m =read();
    	for(ll i = 1; i <= n; i++)
    		w[i] = read();
    	for(ll i = 1; i < n; i++){
    		ll u, v;
    		u = read(), v = read();
    		add(u, v), add(v, u);
    	}
    	dfs1(1, 0);
    	dfs2(1, 1);
    	build(1, n, 1);
    	while(m--){
    		ll op, x, k;
    		op = read();
    		if(op == 1){
    			x = read(), k = read();
    			update(id[x], id[x], k, 1, n, 1);
    		}else if(op == 2){
    			x = read(), k = read();
    			update_Son(x, k);
    		}else{
    			x = read();
    			printf("%lld
    ", query_Range(1, x));
    		}
    	}
    	return 0;
    }
    

    End

    本文来自博客园,作者:xixike,转载请注明原文链接:https://www.cnblogs.com/xixike/p/15108371.html

  • 相关阅读:
    第十二章 并发编程
    信息安全系统设计基础实验四:外设驱动程序设计 20145222黄亚奇 20145213祁玮
    Appium学习笔记||四、获取app页面元素
    安装python3.6(附带PyCharm安装)
    Appium学习笔记||三、获取apk的appPackage和appActivity
    Appium学习笔记||二、环境准备
    Appium学习笔记||一、介绍
    Selenium学习笔记||十九、改变窗口大小
    Selenium学习笔记||十八、使用浏览器copy定位元素表达式
    Selenium学习笔记||十七、制造断点,来查看隐藏菜单元素
  • 原文地址:https://www.cnblogs.com/xixike/p/15108371.html
Copyright © 2011-2022 走看看