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]: ...
随机推荐
- web自动化多次打开浏览器嫌烦?打开一次浏览器,pytest有个招
最近系统前端组件做了更新,我就把之前做的web自动化的代码做了一些修改,顺便优化了下用例,只保留少量的测试用例了,大头还是在接口自动化上.然后发现关于pytest的还有一个点应该比较常用,这里再介绍一 ...
- java控制流程(一)
一.scanner: scanner可以获取用户的输入的信息 scanner的初始化: //导入的包 import java.util.Scanner; public class Test { pub ...
- 1vue snippets
{ "Create vue template": { "prefix": "vue", "body": [ " ...
- vue init深度定制团队自己的Vue template
大家都知道,使用vue-cli可以快速的初始化一个基于Vue.js的项目,全局安装脚手架之后,你可以通过vue list命令看到官方提供的5个模板 vue list 当开发一个独立项目的时候,使用官方 ...
- openshift搭建私有registry
1.创建registry服务器 (1)安装需要的包 yum -y install podman httpd-tools (2)创建registry目录 mkdir -p /opt/registry/{ ...
- Spring Boot 整合Redis 实现缓存
本文提纲 一.缓存的应用场景 二.更新缓存的策略 三.运行 springboot-mybatis-redis 工程案例 四.springboot-mybatis-redis 工程代码配置详解 ...
- leetcode刷题-61旋转链表
题目 给定一个链表,旋转链表,将链表每个节点向右移动 k 个位置,其中 k 是非负数. 示例 1: 输入: 1->2->3->4->5->NULL, k = 2输出: 4 ...
- Mybatis项目构建和CURD操作
Mybatis入门 一.使用SqlSession对象创建Dao接口代理对象进行持久化操作 1.使用maven构建java项目 2.修改pom.xml配置,添加所需jar包坐标 <?xml ver ...
- 使用Azure DevOps Pipeline实现.Net Core程序的CD
上一次我们讲了使用Azure DevOps Pipeline实现.Net Core程序的CI.这次我们来演示下如何使用Azure DevOps实现.Net Core程序的CD. 实现本次目标我们除了A ...
- Readme for Software engineering
作业任务: 软件工程 软件工程 作业要求 作业要求 作业目标 博客园.github注册 自我介绍 软工5问 自我介绍: 广东工业大学计算机学院18级信息安全二班 广东工业大学AD攻防工作室成员& ...