一道树剖的模板题

首先,由于本人比较懒,就把单点修改写成了区间修改,其实也没有有多大区别(关键是我不会写单点修改QAQ)

不得不说,树剖的码量比较大,调了一上午才勉强调完。

这道题要求我们支持 单点修改,区间最大值,区间的和 操作。

我们可以对线段树每个节点 维护一下他的 区间和,以及区间最大值。

其他的就和P3384(树剖模板题)就差不多了。

还有要注意的点是

1 int ans = -2147483647;

求区间和时 答案一定要赋一个负数,因为这道题每个节点的权值有小于 0 的,不赋的话就会爆。

我这个蒟蒻就在这里卡了好几回。

最后附上我自己的代码

  1 #include<iostream>
2 #include<cstdio>
3 #include<algorithm>
4 using namespace std;
5 const int N = 3e4+10;
6 string opt;
7 int n,m,x,y,tot,num;
8 int dfn[N],son[N],head[N],size[N],fa[N];
9 int dep[N],top[N],w[N],a[N];
10 struct node{
11 int to;
12 int net;
13 }e[N*2];
14 void add_(int x,int y){//加边操作
15 tot++;
16 e[tot].to = y;
17 e[tot].net = head[x];
18 head[x] = tot;
19 }
20 void get_tree(int x){//第一遍dfs求每个点的重儿子
21 dep[x] = dep[fa[x]] + 1;
22 size[x] = 1;
23 for(int i = head[x]; i; i = e[i].net){
24 int to = e[i].to;
25 if(to == fa[x]) continue;
26 fa[to] = x;
27 get_tree(to);
28 size[x] += size[to];
29 if(size[to] > size[son[x]]) son[x] = to;
30 }
31 }
32 void dfs(int x,int topp){//第二遍dfs求每个点的top
33 top[x] = topp;
34 dfn[x] = ++num;//每个点的dfs序,方便之后建线段树
35 w[dfn[x]] = a[x];
36 if(son[x]) dfs(son[x],topp);
37 for(int i = head[x]; i; i = e[i].net){
38 int to = e[i].to;
39 if(to == fa[x] || to == son[x]) continue;
40 dfs(to,to);
41 }
42 }
43 struct tree{//线段树常规操作
44 #define l(o) tr[o].lc
45 #define r(o) tr[o].rc
46 #define sum(o) tr[o].sum
47 #define add(o) tr[o].add
48 #define maxn(o) tr[o].maxn
49 struct qxh{
50 int lc,rc;
51 int maxn,add,sum;
52 }tr[N<<2];
53 void up(int o){
54 sum(o) = sum(o*2) + sum(o*2+1);
55 maxn(o) = max(maxn(o*2) , maxn(o*2+1));
56 }
57 void build(int o, int L,int R){//按每个点的dfs序建树
58 l(o) = L; r(o) = R;
59 if(L == R){
60 sum(o) = maxn(o) = w[L];
61 return ;
62 }
63 int mid = (L + R) / 2;
64 build(o*2,L,mid);
65 build(o*2+1,mid+1,R);
66 up(o);
67 }
68 void chenge(int o,int L,int R,int val){//单点修改变区间修改
69 if(L <= l(o) && R >= r(o)){
70 sum(o) = val;
71 maxn(o) = val;
72 return ;
73 }
74 int mid = (l(o) + r(o)) / 2;
75 if(L <= mid) chenge(o*2,L,R,val);
76 if(R > mid) chenge(o*2+1,L,R,val);
77 up(o);
78 }
79 int ask_sum(int o,int L,int R){//询问区间的和
80 int ans = 0;
81 if(L <= l(o) && R >= r(o)){
82 return sum(o);
83 }
84 int mid = (l(o) + r(o)) / 2;
85 if(L <= mid) ans += ask_sum(o*2,L,R);
86 if(R > mid) ans += ask_sum(o*2+1,L,R);
87 return ans;
88 }
89 int ask_max(int o,int L,int R){//区间最大值
90 int ans = -2147483647; //一定要初值为负数,否则就会炸掉
91 if(L <= l(o) && R >= r(o)){
92 return maxn(o);
93 }
94 int mid = (l(o) + r(o)) / 2;
95 if(L <= mid) ans = max(ans,ask_max(o*2,L,R));
96 if(R > mid) ans = max(ans,ask_max(o*2+1,L,R));
97 return ans;
98 }
99 }tree;
100 int query_sum(int x,int y){//求树上路径的和
101 int ans = 0;
102 while(top[x] != top[y]){//边跳边修改
103 if(dep[top[x]] < dep[top[y]]) swap(x,y);
104 ans += tree.ask_sum(1, dfn[top[x]] , dfn[x]);
105 x = fa[top[x]];
106 }
107 if(dep[x] > dep[y]) swap(x,y);//使dfn[x] ~dfn[y]这一段区间的序号保持有序
108 ans += tree.ask_sum(1,dfn[x],dfn[y]);
109 return ans;
110 }
111 int query_max(int x,int y){//求树上路径和,同上
112 int ans = -2147483647;//赋初值。。。。
113 while(top[x] != top[y]){
114 if(dep[top[x]] < dep[top[y]]) swap(x,y);
115 ans = max(ans,tree.ask_max(1,dfn[top[x]],dfn[x]));
116 x = fa[top[x]];
117 }
118 if(dep[x] > dep[y]) swap(x,y);
119 ans = max(ans,tree.ask_max(1,dfn[x],dfn[y]));
120 return ans;
121 }
122 int main(){
123 scanf("%d",&n);
124 for(int i = 1; i <= n-1; i++){
125 scanf("%d%d",&x,&y);
126 add_(x,y);//建双向边
127 add_(y,x);
128 }
129 for(int i = 1; i <= n; i++) scanf("%d",&a[i]);
130 get_tree(1);//预处理
131 dfs(1,1);
132 tree.build(1,1,n);
133 scanf("%d",&m);
134 while(m--){
135 cin>>opt;
136 scanf("%d%d",&x,&y);
137 if(opt == "CHANGE"){
138 tree.chenge(1,dfn[x],dfn[x],y);
139 }
140 if(opt == "QMAX"){
141 printf("%d\n",query_max(x,y));
142 }
143 if(opt == "QSUM"){
144 printf("%d\n",query_sum(x,y));
145 }
146 }
147 return 0;
148 }

代码写的比较丑QAQ ,不喜勿喷。。。。

其实树剖的大部分都是模板题,只要记住两遍dfs就差不多了。

树剖套线段树就是将树剖的模板和线段树的模板凑到一起,每次修改或查询的时候对每条重链或轻链所在的线段树有序区间进行修改或查询。

树剖也就这么多东西。。。

这道题也就结束了,如果看不懂的可以看看Treaker (我们上届一位巨佬,会各种奇奇怪怪的树)的题解,他写的也挺好的 %%%%%

想练习树剖的可以做一下下面这几道题

  1. 轻重链剖分
  2. 软件包管理器
  3. 松鼠的新家
  4. 月下毛景树
  5. 旅行
  6. 旅游
  7. 运输计划
  8. 天天爱跑步

这些都是我们可爱的Treaker学长留的好题(毒瘤题,每道题都要调很久)。。。QAQ

本篇题解到这里就结束了。撒花✿✿ヽ(°▽°)ノ✿

树剖未完待续。。。。。QAQ

P2590 树的统计的更多相关文章

  1. Luogu P2590 树的统计(树链剖分+线段树)

    题意 原文很清楚了 题解 重链剖分模板题,用线段树维护即可. #include <cstdio> #include <cstring> #include <algorit ...

  2. 洛谷 [P2590] 树的统计

    迷之TLE #include <iostream> #include <cstdio> #include <cstring> #include <algori ...

  3. P2590 [ZJOI2008]树的统计(树链剖分)

    P2590 [ZJOI2008]树的统计 虽然是入门树剖模板 但是我终于1A了(大哭) 懒得写啥了(逃 #include<iostream> #include<cstdio> ...

  4. 树链剖分【洛谷P2590】 [ZJOI2008]树的统计

    P2590 [ZJOI2008]树的统计 题目描述 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w. 我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把 ...

  5. P2590 [ZJOI2008]树的统计(LCT)

    P2590 [ZJOI2008]树的统计 题目描述 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w. 我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把 ...

  6. 洛谷——P2590 [ZJOI2008]树的统计(树链剖分模板练手)

    P2590 [ZJOI2008]树的统计 I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问 ...

  7. 洛谷P2590 [ZJOI2008] 树的统计 [树链剖分]

    题目传送门 树的统计 题目描述 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w. 我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t ...

  8. Luogu P2590 [ZJOI2008]树的统计

    最近在学树剖,看到了这题就做了 [ZJOI2008]树的统计 思路 从题面可以知道,这题是树剖题(要求的和模板没什么区别呀喂 就是在普通的树剖上加了一个最大值 所以可以知道就是树剖+特殊的线段树 线段 ...

  9. 洛谷P2590 [ZJOI2008]树的统计 题解 树链剖分+线段树

    题目链接:https://www.luogu.org/problem/P2590 树链剖分模板题. 剖分过程要用到如下7个值: fa[u]:u的父节点编号: dep[u]:u的深度: size[u]: ...

随机推荐

  1. 腾讯大牛半年心血高级编程PDF,帮你轻松构建企业级Web应用

    毫无疑问,Java 是这些年来最流行的编程语言之一.它无处不在一计算机. 手机.网站以及各种嵌入式设备中都存在着大量的Java 应用程序,而其中应用最为广泛的应该就是Java EE Web应用程序(以 ...

  2. The Data Warehouse Toolkit 阅读笔记

    前言 这篇笔记的主要内容来至于The Data Warehouse Toolkit,该书可以称为数仓建模的圣经 什么是星型模型 以一个业务实时为主表.比如一笔订单就是一个业务事实.订单有商品的SKU信 ...

  3. Android studio Debug 源码

    原来有的地方打不了断点 会提示no executable code at line xxx 源码sdk里有,sdkManager下好对应版本,然后使用对应版本的模拟器debug就行了 如果要debug ...

  4. 算法专题 | 10行代码实现的最短路算法——Bellman-ford与SPFA

    今天是算法数据结构专题的第33篇文章,我们一起来聊聊最短路问题. 最短路问题也属于图论算法之一,解决的是在一张有向图当中点与点之间的最短距离问题.最短路算法有很多,比较常用的有bellman-ford ...

  5. 【jmespath】—1. 基础用法

    一.jsonpath 之前我写接口自动化测试时候,对于复杂的json返回,会使用jsonpath这个第三方库,就像写xpath一样,方便的查询json元素. 因为之前写WEB自动化时候,总用xpath ...

  6. 分布式ID生成方案汇总

    1.目标 1.1.全局唯一 不能出现重复的ID,全局唯一是最基本的要求. 1.2.趋势有序 业务上分页查询需求,排序需求,如果ID直接有序,则不必建立更多的索引,增加查询条件. 而且Mysql Inn ...

  7. JavaScript 的 this 指向和绑定详解

    JavaScript 中的 new.bind.call.apply 实际这些都离不开 this,因此本文将着重讨论 this,在此过程中分别讲解其他相关知识点. 注意: 本文属于基础篇,请大神绕路.如 ...

  8. js拖拽原理及简单实现(渣渣自学)

    第一步 首先简单分析下需求吧,我们就是想实现鼠标拖拽带颜色的方块时,让方块停留在鼠标松开的位置,需要计算的就是拖拽前的坐标和拖拽后的坐标,鼠标移动后相对于原位置的偏移量=目标元素的偏移量,根据这个等式 ...

  9. 手把手带你体验鸿蒙 harmonyOS

    wNlRGd.png 前言 本文已经收录到我的 Github 个人博客,欢迎大佬们光临寒舍: 我的 GIthub 博客 学习导图 image.png 一.为什么要尝鲜 harmonyos? wNlfx ...

  10. [LeetCode]64. 最小路径和(DP)

    题目 给定一个无序的整数数组,找到其中最长上升子序列的长度. 示例: 输入: [10,9,2,5,3,7,101,18] 输出: 4 解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4 ...