一道树剖的模板题

首先,由于本人比较懒,就把单点修改写成了区间修改,其实也没有有多大区别(关键是我不会写单点修改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. Cubmap

    视差 Cubmap https://chengkehan.github.io/LocalCubmap.html http://www.manew.com/thread-93923-1-1.html h ...

  2. unity接入安卓SDK,与安卓相互通信

    .接SDK是个什么样的活计? SDK的工作流程: 1. 从unity端出发,向安卓发起一系列的请求(unity call android). 2. 安卓端收到unity端调用,然后在具体调用SDK的一 ...

  3. unity5打包机制下,一种资源打ab和资源管理的方案

    unity5打包机制下,一种资源打ab和资源管理的方案.1.打ab: 1.设置平台 2.清楚所有资源的assetbundlename: string[] abNameArr = AssetDataba ...

  4. [BUUOJ记录] [ZJCTF 2019]NiZhuanSiWei

    考察PHP伪协议+反序列化,都比较简单 进入题目给出源码: <?php $text = $_GET["text"]; $file = $_GET["file&quo ...

  5. KUDU 学习笔记

    Kudu 现存系统针对结构化数据存储与查询的一些痛点问题,结构化数据的存储,通常包含如下两种方式: 静态数据通常以Parquet/Carbon/Avro形式直接存放在HDFS中,吞吐能力大,适合离线分 ...

  6. List集合对象去重及按属性去重的8种方法-java基础总结系列第六篇

    最近在写一些关于java基础的文章,但是我又不想按照教科书的方式去写知识点的文章,因为意义不大.基础知识太多了,如何将这些知识归纳总结,总结出优缺点或者是使用场景才是对知识的升华.所以我更想把java ...

  7. IIS上传文件最大限制问题

    IIS服务器文件最大限制默认是30M. 自定义方法:修改配置文件,路径是:C:\Windows\System32\inetsrv\Config\applicationHost.config 在requ ...

  8. intellij idea 无法进行调试的解决方案

    inteliij idea 如果出现无法调试该怎样做?debug中各功能为灰色. 如果你用的是外来项目,可能是没有添加这个项目自带的library: 解决办法: 在file->project  ...

  9. 利用ANSI转义序列在控制台输出彩色文字

    说明:无论什么语言,只要你的终端能够解释ANSI转义序列(大多数的类unix终端仿真器都能够解释ANSI转义序列,win32控制台则不支持),就能够使用ANSI转义序列输出颜色.这个功能看似鸡肋,但只 ...

  10. vue父子组件状态同步的最佳方式

    哈喽!大家好!我是木瓜太香,一位老牌儿前端工程师,平时我们在使用 vue 开发的时候,可能会遇到需要父组件与子组件某个状态需要同步的情况,通常这个是因为我们封装组件的时候有一个相同的状态外面要用,里面 ...