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;
    }
    

      

    寻找真正的热爱
  • 相关阅读:
    Linux命令选项及参数解析 getopt() getopt_long() 函数
    找不到文件或程序集名称“DreamweaverCtrls”的解决方法
    #include file 与#include virtual的区别
    用dw(dreamweaver)开发asp.net,连接数据库时出现“http错误500,服务器内部错误”的解决方法
    [ASP.Net]ASP.NET中上传文件
    [.net]"Request.Form出现乱码"的解决方法
    正式进驻博客园
    [ASP.NET] 限制上传文件类型的两种方法(转)
    错误类型:“系统找不到 Microsoft.Office.Interop.Word"
    从客户端检测到有潜在危险的Request.Form 值
  • 原文地址:https://www.cnblogs.com/lesning/p/12384793.html
Copyright © 2011-2022 走看看