P2590 树的统计
一道树剖的模板题
首先,由于本人比较懒,就把单点修改写成了区间修改,其实也没有有多大区别(关键是我不会写单点修改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 (我们上届一位巨佬,会各种奇奇怪怪的树)的题解,他写的也挺好的 %%%%%
想练习树剖的可以做一下下面这几道题
这些都是我们可爱的Treaker学长留的好题(毒瘤题,每道题都要调很久)。。。QAQ
本篇题解到这里就结束了。撒花✿✿ヽ(°▽°)ノ✿
树剖未完待续。。。。。QAQ
P2590 树的统计的更多相关文章
- Luogu P2590 树的统计(树链剖分+线段树)
题意 原文很清楚了 题解 重链剖分模板题,用线段树维护即可. #include <cstdio> #include <cstring> #include <algorit ...
- 洛谷 [P2590] 树的统计
迷之TLE #include <iostream> #include <cstdio> #include <cstring> #include <algori ...
- P2590 [ZJOI2008]树的统计(树链剖分)
P2590 [ZJOI2008]树的统计 虽然是入门树剖模板 但是我终于1A了(大哭) 懒得写啥了(逃 #include<iostream> #include<cstdio> ...
- 树链剖分【洛谷P2590】 [ZJOI2008]树的统计
P2590 [ZJOI2008]树的统计 题目描述 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w. 我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把 ...
- P2590 [ZJOI2008]树的统计(LCT)
P2590 [ZJOI2008]树的统计 题目描述 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w. 我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把 ...
- 洛谷——P2590 [ZJOI2008]树的统计(树链剖分模板练手)
P2590 [ZJOI2008]树的统计 I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问 ...
- 洛谷P2590 [ZJOI2008] 树的统计 [树链剖分]
题目传送门 树的统计 题目描述 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w. 我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t ...
- Luogu P2590 [ZJOI2008]树的统计
最近在学树剖,看到了这题就做了 [ZJOI2008]树的统计 思路 从题面可以知道,这题是树剖题(要求的和模板没什么区别呀喂 就是在普通的树剖上加了一个最大值 所以可以知道就是树剖+特殊的线段树 线段 ...
- 洛谷P2590 [ZJOI2008]树的统计 题解 树链剖分+线段树
题目链接:https://www.luogu.org/problem/P2590 树链剖分模板题. 剖分过程要用到如下7个值: fa[u]:u的父节点编号: dep[u]:u的深度: size[u]: ...
随机推荐
- python给excel文件加密码,并重新生成文件
需安装pywin32 pip install pywin32 直接上源码.简单几行就搞定 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手. ...
- 算法专题 | 10行代码实现的最短路算法——Bellman-ford与SPFA
今天是算法数据结构专题的第33篇文章,我们一起来聊聊最短路问题. 最短路问题也属于图论算法之一,解决的是在一张有向图当中点与点之间的最短距离问题.最短路算法有很多,比较常用的有bellman-ford ...
- indexOf原理,Java,javascript,python实现
简介 最近做项目的时候,发现无论是前端还是后端,indexOf出现的概率都非常频繁,今天我们来看下他的实现原理吧! indexOf的含义:给定一个字符串去匹配另一个字符串的下标,如果匹配到,返回下 ...
- java-介绍函数理解重载
package day02; public class FunctionOverload { public static void main(String[] args){ int a = add(, ...
- mysql jdbc连接时的小问题java.sql.SQLException: Access denied for user 'root'@'localhost' (using password: YES)
这次重新修改老程序时出现了上面的错误,排查过后最终找到问题所在:root帐户默认不开放远程访问权限,所以需要修改一下相关权限. 打开MySQL目录下的my.ini文件(win10默认安装在C:\Pro ...
- lua数据结构之table的内部实现
一.table结构 1.Table结构体 首先了解一下table结构的组成结构,table是存放在GCObject里的.结构如下: typedef struct Table { CommonH ...
- 小程序开发-6个优秀的UI组件库
微信小程序开发,当原生的控件不能满足我们时,可以尝试下面几个比较优秀的组件库. 1. WeUI WXSS WeUI WXSS是腾讯官方UI组件库WeUI的小程序版,提供了跟微信界面风格一致的用户体验. ...
- golang开发:CSP-WaitGroup Mutex
CSP 是 Communicating Sequential Process 的简称,中文可以叫做通信顺序进程,是一种并发编程模型,最初于Tony Hoare的1977年的论文中被描述,影响了许多编程 ...
- 云计算openstack共享组件——时间同步服务ntp(2)
一.标准时间讲解 地球分为东西十二个区域,共计 24 个时区 格林威治作为全球标准时间即 (GMT 时间 ),东时区以格林威治时区进行加,而西时区则为减. 地球的轨道并非正圆,在加上自转速度逐年递减, ...
- 将lua编译进nginx
1.先安装lua-jit,网上说也可以下载lua,不过lua-jit效率比较高,地址:http://luajit.org/download.html我下的是2.0.3版本的下载解压后,直接make & ...