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

    我感觉就是线段树+LCA的思想了

    核心还是线段树

    需要注意

    在标记中,一个节点的所有子孙一定都是标号小于该节点的。

    https://www.luogu.com.cn/problem/P2590

    洛谷例题

    解答

    功能变多了就会很长很长

    #include<cstring>
    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<vector>
    using namespace std;
    typedef long long ll;
    const int maxn = 1e5 + 7;
    
    vector<int>G[maxn];
    
    int n;
    void add(int x, int y) {
    	G[x].push_back(y);
    }
    int dep[maxn], top[maxn], id[maxn], fa[maxn], siz[maxn];
    
    int son[maxn];
    
    ll list[maxn];//初始编号
    ll cns[maxn];//改动后用来建线段树的编号
    
    ll sum[4 * maxn];//求和
    ll mx[4 * maxn];
    
    int dfs1(int x, int f,int d) {
    	dep[x] = d;
    	fa[x] = f;
    	siz[x] = 1;
    	int s = 0;
    	for (int i = 0; i < G[x].size(); i++) {
    		int p = G[x][i];
    		if (p == f) continue;
    		dfs1(p, x, d + 1);
    		siz[x] += siz[p];
    		if (s < siz[p]) {
    			s = siz[p];
    			son[x] = p;
    		}
    	}
    	return 0;
    }//haah
    int cnt;
    int dfs2(int x,int t) {
    	id[x] = ++cnt;
    	cns[cnt] = list[x];
    	top[x] = t;
    	if (!son[x]) return 0;
    	dfs2(son[x], t);//重儿子重复利用t
    
    	for (int i = 0; i < G[x].size();i++) {
    		int p = G[x][i];
    		if (p == fa[x] || p == son[x]) continue;
    		dfs2(p, p);//轻儿子新建t
    	}
    	return 0;
    }
    
    int bulit(int node, int be, int en) {
    	if (be == en) {
    		mx[node] = cns[be];
    		sum[node] = cns[be];
    		return 0;
    	}
    	int l = node * 2;
    	int r = node * 2 + 1;
    
    	int mid = (be + en) / 2;
    	bulit(l, be, mid);
    	bulit(r, mid + 1, en);
    	sum[node] = sum[l] + sum[r];
    	mx[node] = max(mx[l], mx[r]);
    	return 0;
    }
    
    int update(int node, int be, int en, int i, int val) {
    	if (be == en) {
    		sum[node] = val;
    		mx[node] = val;
    		return 0;
    	}
    	int l = node * 2;
    	int r = node * 2 + 1;
    	int mid = (be + en) / 2;
    
    	if (i <= mid) update(l, be, mid, i, val);
    	else update(r, mid + 1, en, i, val);
    
    	sum[node] = sum[l] + sum[r];
    	mx[node] = max(mx[l], mx[r]);
    
    	return 0;
    }
    ll qurry_sum(int node, int be, int en, int LL, int RR) {
    	if (LL > en || RR < be) return 0;
    	if (LL <= be && RR >= en) {
    		return sum[node];
    	}
    	int l = node * 2;
    	int r = node * 2 + 1;
    	int mid = (be + en) / 2;
    	ll val1 = qurry_sum(l, be, mid, LL, RR);
    	ll val2 = qurry_sum(r, mid + 1, en, LL, RR);
    	return val1 + val2;
    }
    
    ll qurry_max(int node, int be, int en, int LL, int RR) {
    	if (LL > en || RR < be) return -1e10;
    	
    	if (LL <= be && en <= RR) {
    		return mx[node];
    	}
    	int l = node * 2;
    	int r = node * 2 + 1;
    	int mid = (be + en) / 2;
    	ll val1 = qurry_max(l, be, mid, LL, RR);
    	ll val2 = qurry_max(r, mid + 1, en, LL, RR);
    	return max(val1, val2);
    }
    
    
    ll qrank_max(int x, int y) {
    	ll ans = -1e18;
    	while (top[x] != top[y]) {
    		if (dep[top[x]] < dep[top[y]]) swap(x, y);
    		ll cns = qurry_max(1, 1, n, id[top[x]], id[x]);
    		ans = max(ans, cns);
    		x = fa[top[x]];
    	}
    	//现在两个点在一个重链上了
    	if (dep[x] > dep[y]) swap(x, y);
    	//x现在在y上面,id更小
    	ll cns = qurry_max(1, 1, n, id[x], id[y]);//注意顺序
    	ans = max(ans, cns);
    	return ans;
    }
    
    
    ll qrank_sum(int x, int y) {
    	ll ans = 0;
    	while (top[x] != top[y]) {
    		if (dep[top[x]] < dep[top[y]]) swap(x, y);
    		ll cns = qurry_sum(1, 1, n, id[top[x]], id[x]);
    		ans += cns;
    		x = fa[top[x]];
    	}
    	//现在两个点在一个重链上了
    	if (dep[x] > dep[y]) swap(x, y);
    	//x现在在y上面,id更小
    	ll cns = qurry_sum(1, 1, n, id[x], id[y]);//注意顺序
    	ans += cns;
    	return ans;
    }
    
    
    char op[20];
    
    
    int main() {
    	scanf("%d", &n);
    	for (int i = 1; i < n; i++) {
    		int x, y;
    		scanf("%d%d", &x, &y);
    		add(x, y);
    		add(y, x);
    	}
    	for (int i = 1; i <= n; i++) {
    		scanf("%lld", &list[i]);
    	}
    
    	dfs1(1, -1, 0);
    	dfs2(1, 1);
    	bulit(1, 1, n);
    	
    	int q;
    	scanf("%d", &q);
    	while (q--) {
    		int x, y;
    		scanf("%s", op);
    		scanf("%d %d", &x, &y);
    		ll ans = 0;
    
    		if (op[1] == 'H') {
    			update(1, 1, n, id[x], y);
    		}
    		else if (op[1] == 'M') {
    			ans = qrank_max(x, y);
    			printf("%lld
    ", ans);
    		}
    		else if (op[1] == 'S') {
    			ans = qrank_sum(x, y);
    			printf("%lld
    ", ans);
    		}
    
    	}
    	return 0;
    }
    

      

    寻找真正的热爱
  • 相关阅读:
    _bzoj1061 [Noi2008]志愿者招募【最小费用最大流】
    _bzoj2243 [SDOI2011]染色【树链剖分】
    _bzoj1013 [JSOI2008]球形空间产生器sphere【高斯消元】
    _bzoj1002 [FJOI2007]轮状病毒【瞎搞】
    leetcode 273 Integer to English Words
    leetcode 12 Integer to Roman
    leetcode 1071 Greatest Common Divisor of Strings
    lc6 ZigZag Conversion
    lc13 Roman to Integer
    leetcode 171 Excel Sheet Column Number
  • 原文地址:https://www.cnblogs.com/lesning/p/12384793.html
Copyright © 2011-2022 走看看