比较基础的一道树链剖分的题 大概还是得说说思路

  树链剖分是将树剖成很多条链,比较常见的剖法是按儿子的size来剖分,剖分完后对于这课树的询问用线段树维护——比如求路径和的话——随着他们各自的链向上走,直至他们在同一条链上为止。比较像lca的方法,只不过这里是按链为单位,而且隔壁的SymenYang说可以用树链剖分做lca。。吓哭

  然后说说惨痛的调题经历:边表一定要开够啊! 不是n-1 而是2*(n-1)啊! 然后写变量时原始值和映射值要搞清楚啊! 不要搞错了! 还有就是下次求最小值一定看清下界是多少! 树的统计是-30000 ~ 30000 ,我果断naive 的写了一个初值为0!!! wa 0 就是这么痛苦! 还是too Young too Simple !

code :

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 using namespace std;
  6
  7 const int maxn = 50001;
  8
  9 struct edge{
 10     int t; edge* next;
 11 }e[maxn*3], *head[maxn];int ne = 0;
 12
 13 void addedge(int f, int t){
 14     e[ne].t = t; e[ne].next = head[f]; head[f] = e + ne ++;
 15 }
 16
 17 int n;
 18 int size[maxn],fa[maxn],dep[maxn],w[maxn],un[maxn],map[maxn];
 19
 20 struct node{
 21     int smax, sum;
 22     node *l, *r;
 23 }tr[maxn * 3], *root; int trne = 0;
 24
 25 node* build(int l, int r){
 26     node* x = tr + trne ++;
 27     if(l != r) {
 28         int mid = (l + r) >> 1;
 29         x-> l = build(l, mid);
 30         x-> r = build(mid + 1, r);
 31     }
 32     return x;
 33 }
 34
 35 void update(node* x){
 36     if(x-> l) {
 37         x-> sum = x-> l-> sum + x-> r->sum;
 38         x-> smax = max(x-> l-> smax, x-> r-> smax);
 39     }
 40 }
 41
 42 void insert(node* x, int l, int r, int pos, int v) {
 43     if(l == r) { x-> sum = v, x-> smax = v;}
 44     else{
 45         int mid = (l + r) >> 1;
 46         if(pos <= mid) insert(x-> l, l, mid, pos, v);
 47         else insert(x-> r, mid + 1, r, pos, v);
 48         update(x);
 49     }
 50 }
 51
 52 int ask(node* x, int l, int r, int ls, int rs, int flag) {
 53     if(l == ls && r == rs) {
 54         if(flag == 0) return x-> smax;
 55         else return x-> sum;
 56     }
 57     else {
 58         int mid = (l + r) >> 1;
 59         if(rs <= mid) return ask(x-> l, l, mid, ls, rs, flag);
 60         else if(ls >= mid + 1) return ask(x-> r, mid + 1, r, ls, rs, flag);
 61         else {
 62             if(flag == 0)
 63                 return max(ask(x->l, l, mid, ls, mid, flag), ask(x-> r, mid + 1, r, mid + 1, rs, flag));
 64             else
 65                 return ask(x-> l, l, mid, ls, mid, flag) + ask(x-> r, mid + 1, r, mid + 1, rs, flag);
 66         }
 67     }
 68 }
 69
 70 int cnt = 0;
 71
 72 void size_cal(int x, int pre) {
 73     if(pre == -1) dep[x] = 1, fa[x] = x;
 74     else dep[x] = dep[pre] + 1, fa[x] = pre;
 75
 76     size[x] = 1;
 77     for(edge* p = head[x]; p; p = p-> next)
 78         if(dep[p-> t] == -1)size_cal(p-> t, x), size[x] += size[p-> t];
 79 }
 80
 81 void divide(int x, int pre){
 82     if(pre == -1) un[x] = x;
 83     else un[x] = un[pre];
 84     map[x] = ++ cnt; insert(root, 1, n, map[x], w[x]);
 85     int tmax = -1, ts = -1;
 86     for(edge* p = head[x]; p; p = p-> next) {
 87         if(dep[p-> t] > dep[x] && size[p-> t] > tmax) tmax = size[p-> t], ts = p-> t;
 88     }
 89     if(ts != -1) {
 90         divide(ts, x);
 91         for(edge* p = head[x]; p; p = p-> next) {
 92             if(dep[p-> t] > dep[x] && p-> t != ts) divide(p-> t, -1);
 93         }
 94     }
 95 }
 96
 97 void read() {
 98     memset(dep,-1,sizeof(dep));
 99     scanf("%d", &n);
100     root = build(1, n);
101     for(int i = 1; i <= n - 1; i++) {
102         int f, t;
103         scanf("%d%d", &f, &t);
104         addedge(f, t), addedge(t, f);
105     }
106     for(int i = 1; i <= n; ++ i) {
107         scanf("%d", &w[i]);
108     }
109     size_cal(1, -1);divide(1, -1);
110 }
111
112 int sovmax(int a, int b) {
113     int ans = -30001; int ls, rs;
114     while(un[a] != un[b]) {
115         if(dep[un[a]] > dep[un[b]]) {
116             ls = map[a]; rs = map[un[a]];
117             if(ls > rs) swap(ls, rs);
118             ans = max(ans, ask(root, 1, n, ls, rs, 0));
119             a = fa[un[a]];
120         }
121         else {
122             ls = map[b]; rs = map[un[b]];
123             if(ls > rs) swap(ls, rs);
124             ans = max(ans, ask(root, 1, n, ls, rs, 0));
125             b = fa[un[b]];
126             }
127     }
128     ls = map[a], rs = map[b];
129     if(ls > rs) swap(ls,rs);
130     ans = max(ans, ask(root, 1, n, ls, rs, 0));
131     return ans;
132 }
133
134 int sovsum(int a,int b) {
135     int ans = 0; int ls, rs;
136     while(un[a] != un[b]) {
137         if(dep[un[a]] > dep[un[b]]) {
138             ls = map[a], rs = map[un[a]];
139             if(ls > rs) swap(ls, rs);
140             ans += ask(root, 1, n, ls, rs, 1);
141             a = fa[un[a]];
142         }
143         else {
144             ls = map[b]; rs = map[un[b]];
145             if(ls > rs) swap(ls, rs);
146             ans += ask(root, 1, n, ls, rs, 1);
147             b = fa[un[b]];
148         }
149     }
150     ls = map[a], rs = map[b];
151     if(ls > rs) swap(ls, rs);
152     ans += ask(root, 1, n, ls, rs, 1);
153     return ans;
154 }
155
156 void sov() {
157     int m;
158     scanf("%d", &m);
159     while(m --) {
160         char s[10]; int ls, rs;
161         scanf("%s %d%d", s + 1, &ls, &rs);
162         if(s[2] == 'M') printf("%d\n", sovmax(ls, rs));
163         if(s[2] == 'S') printf("%d\n", sovsum(ls, rs));
164         if(s[2] == 'H') insert(root, 1, n, map[ls], rs);
165     }
166 }
167
168 int main(){
169     read();sov();
170     return 0;
171 }

View Code

转载于:https://www.cnblogs.com/ianaesthetic/p/3773924.html

zjoi 2008 树的统计——树链剖分相关推荐

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

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

  2. BZOJ1036[ZJOI2008]树的统计——树链剖分+线段树

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

  3. P3899 [湖南集训]更为厉害(线段树合并、长链剖分、二维数点)

    P3899 [湖南集训]更为厉害 若 deepb<deepa\text{deep}_b<\text{deep}_adeepb​<deepa​:c 在点 a 的子树中,根据乘法原理计算 ...

  4. [LOJ3014][JOI 2019 Final]独特的城市——树的直径+长链剖分

    题目链接: [JOI 2019 Final]独特的城市 对于每个点,它的答案最大就是与它距离最远的点的距离. 而如果与它距离为$x$的点有大于等于两个,那么与它距离小于等于$x$的点都不会被计入答案. ...

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

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

  6. ZJOI2008 树的统计 树链剖分学习

    水题,这次都没有给我傻逼的机会了,1A过了.直接上代码了 #include <iostream> #include <cstdio> #include <cstring& ...

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

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

  8. 【树链剖分】【线段树】树的统计(金牌导航 树链剖分-1)

    树的统计 金牌导航 树链剖分-1 题目大意 给出一棵树,让你做若干操作,操作如下: 1.修改一个节点的值 2.查询两个节点之间路径的最大值 3.查询两个节点之间路径的和 输入样例 4 1 2 2 3 ...

  9. 树链剖分入门+HYSBZ - 1036树的统计Count

    今天学习了树链剖分,记录一下. [题目背景] HYSBZ - 1036树的统计Count [题目分析] 题目要求求任意结点之间路径的和以及路径上最大的结点,还有可能修改.如果正常做可能会很复杂(我也不 ...

最新文章

  1. 编译-C语言库FFTW支持iOS平台的静态库
  2. 2.05亿美元!马斯克Neuralink获脑机接口领域史上最大融资,公司正急招软件工程师...
  3. 信息安全系统设计基础第十二周学习总结
  4. C 语言里的字符串---字符数组
  5. find 命令_Linux下查找文件:find 命令
  6. ubuntu10.04 MTK开发环境
  7. linux opendir php,php目录遍历函数opendir用法实例
  8. 【数据分析】数据分析达人赛3:汽车产品聚类分析
  9. Apache启动失败,请检查相关配置。√MySQL5.1已启动。
  10. html添加右键菜单,JS添加右键菜单
  11. 2022《福布斯》富豪榜发布,FTX联合创始人Gary Wang上榜
  12. GUI学习笔记——04更改背景板颜色,鼠标进入事件
  13. 面向对象[方法]定义一个长方形类,定义 求周长和面积的方法
  14. 关于pr文件导入的问题
  15. 三星新旗舰手机 GALAXY S III正式发布
  16. 1241. 外卖店优先级 Java题解 (模拟)【第十届蓝桥杯省赛C++A/C组,JAVA A/B/C组】
  17. 计算机网络存在的漏洞,常见的计算机网络安全漏洞有哪些
  18. 收藏 网页设计的常识!
  19. php数组和链表的区别,什么是链表?链表与数组的区别?
  20. 用HTML5图形拼成的画房子,canvas画小房子(补充:简陋的小房子)

热门文章

  1. Something about TFS
  2. rollup配置及使用
  3. LeetCode(225)——用队列实现栈(JavaScript)
  4. 我的webpack路
  5. 文件上传 文件大小和类型
  6. JavaScript学习(八十八)—数组知识点总结,超详细!!!
  7. 六级词汇打卡第一天(一)
  8. 我在一家通信公司上班
  9. 感觉养老金越涨差距越大,有人提议高于5000的不再上涨,合理吗?
  10. 中年人需要写个遗嘱吗?