bzoj3531: [Sdoi2014]旅行 (树链剖分 动态开点线段树)
感觉动态开点线段树空间复杂度好优秀呀
树剖裸题
把每个宗教都开一颗线段树就可以了
但是我一直TLE
然后调了一个小时
为什么呢
因为我 #define max(x, y) (x > y ? x : y)
看起来好像可以减少常数的样子
我也是这么想的(作死
事实上
ans = max(ans, query(x, y))
类似这种语句中
query(x, y)会计算两次
然后就GG了
这告诉我们还是好好用库里的函数吧
1 #include <cstdio> 2 #include <algorithm> 3 #include <vector> 4 using namespace std; 5 const int N = 100000 + 10; 6 const int M = 2000000 + 10; 7 #define isdigit(x) (x >= '0' && x <= '9') 8 9 inline void read(int &ans) { 10 ans = 0; 11 static char buf = getchar(); 12 register int res = 1; 13 for (; !isdigit(buf); buf = getchar()) 14 if (buf == '-') res = -1; 15 for (; isdigit(buf); buf = getchar()) 16 ans = ans * 10 + buf - '0'; 17 ans *= res; 18 } 19 20 int tot, n, q; 21 int sz[N], hs[N], pos[N], fa[N], top[N], w[N], c[N], dep[N]; 22 vector < int > E[N]; 23 24 void dfs1(int x, int d, int f) { 25 dep[x] = d; fa[x] = f; 26 hs[x] = -1; sz[x] = 1; 27 int tmp = 0; 28 for (int i = 0; i < E[x].size(); i++) { 29 int u = E[x][i]; 30 if (u == f) continue; 31 dfs1(u, d + 1, x); 32 sz[x] += sz[u]; 33 if (tmp < sz[u]) 34 tmp = sz[u], hs[x] = u; 35 } 36 } 37 38 void dfs2(int x, int t) { 39 top[x] = t; pos[x] = ++tot; 40 if (hs[x] == -1) return; 41 dfs2(hs[x], t); 42 for (int i = 0; i < E[x].size(); i++) 43 if (E[x][i] != fa[x] && E[x][i] != hs[x]) 44 dfs2(E[x][i], E[x][i]); 45 } 46 47 int cnt; 48 int sum[M], maxn[M], ls[M], rs[M], root[N]; 49 50 inline void pushUp(int o) { 51 maxn[o] = max(maxn[ls[o]], maxn[rs[o]]); 52 sum[o] = sum[ls[o]] + sum[rs[o]]; 53 } 54 55 void modify(int &o, int l, int r, int p, int c) { 56 if (!o) o = ++cnt; 57 if (l == r) { 58 sum[o] = maxn[o] = c; 59 return ; 60 } 61 int mid = l + r >> 1; 62 if (p <= mid) modify(ls[o], l, mid, p, c); 63 else modify(rs[o], mid + 1, r, p, c); 64 pushUp(o); 65 } 66 67 int querySum(int o, int l, int r, int L, int R) { 68 if (!o) return 0; 69 if (l >= L && r <= R) return sum[o]; 70 int mid = l + r >> 1, ans = 0; 71 if (L <= mid) ans += querySum(ls[o], l, mid, L, R); 72 if (R > mid) ans += querySum(rs[o], mid + 1, r, L, R); 73 return ans; 74 } 75 76 inline int querySum(int c, int x, int y) { 77 int f1 = top[x], f2 = top[y]; 78 int ans = 0; 79 while (f1 != f2) { 80 if (dep[f1] < dep[f2]) 81 swap(x, y), swap(f1, f2); 82 ans += querySum(root[c], 1, n, pos[f1], pos[x]); 83 x = fa[f1]; f1 = top[x]; 84 } 85 if (dep[x] > dep[y]) swap(x, y); 86 ans += querySum(root[c], 1, n, pos[x], pos[y]); 87 return ans; 88 } 89 90 int queryMax(int o, int l, int r, int L, int R) { 91 if (!o) return 0; 92 if (l >= L && r <= R) return maxn[o]; 93 int mid = l + r >> 1, ans = 0; 94 if (L <= mid) ans = max(ans, queryMax(ls[o], l, mid, L, R)); 95 if (R > mid) ans = max(ans, queryMax(rs[o], mid + 1, r, L, R)); 96 return ans; 97 } 98 99 inline int queryMax(int c, int x, int y) { 100 int f1 = top[x], f2 = top[y]; 101 int ans = 0; 102 while (f1 != f2) { 103 if (dep[f1] < dep[f2]) 104 swap(x, y), swap(f1, f2); 105 ans = max(ans, queryMax(root[c], 1, n, pos[f1], pos[x])); 106 x = fa[f1]; f1 = top[x]; 107 } 108 if (dep[x] > dep[y]) swap(x, y); 109 ans = max(ans, queryMax(root[c], 1, n, pos[x], pos[y])); 110 return ans; 111 } 112 113 114 int main() { 115 read(n); read(q); 116 for (int i = 1; i <= n; i++) 117 read(w[i]), read(c[i]); 118 for (int i = 1; i < n; i++) { 119 int u, v; 120 read(u); read(v); 121 E[u].push_back(v); 122 E[v].push_back(u); 123 } 124 dfs1(1, 0, 0); dfs2(1, 1); 125 for (int i = 1; i <= n; i++) 126 modify(root[c[i]], 1, n, pos[i], w[i]); 127 for (int i = 1; i <= q; i++) { 128 char ch[5]; scanf("%s", ch); 129 int x, y; read(x); read(y); 130 if (ch[0] == 'C') { 131 if (ch[1] == 'C') { 132 modify(root[c[x]], 1, n, pos[x], 0); 133 c[x] = y; 134 modify(root[y], 1, n, pos[x], w[x]); 135 } 136 else { 137 modify(root[c[x]], 1, n, pos[x], y); 138 w[x] = y; 139 } 140 } 141 else { 142 if (ch[1] == 'S') 143 printf("%d\n", querySum(c[x], x, y)); 144 else printf("%d\n", queryMax(c[x], x, y)); 145 } 146 } 147 return 0; 148 }
转载于:https://www.cnblogs.com/cminus/p/8598748.html
bzoj3531: [Sdoi2014]旅行 (树链剖分 动态开点线段树)相关推荐
- [LuoguU41039]PION后缀自动机 树链剖分+动态开点线段树
链接 刚开始看出题人题解都吓蒙掉了,还以为是什么难题,结果就一板子题 思路:对每一个文件名开一棵线段树,然后树剖即可 #include<bits/stdc++.h> #define REP ...
- hdu3966 树链剖分点权模板+线段树区间更新/树状数组区间更新单点查询
点权树的模板题,另外发现树状数组也是可以区间更新的.. 注意在对链进行操作时方向不要搞错 线段树版本 #include<bits/stdc++.h> using namespace std ...
- 动态开点线段树(多棵线段树)的内存分配与回收
前言 线段树,是一个很好用的能支持O(logn)区间操作的数据结构,随着做一些稍微烦一点的题,有时候会发现有些情况要开一个数组的线段树,更有甚者要树套树,而在很多情况下线段树就不能把所有点都开满了(否 ...
- NOIP2017 列队——动态开点线段树
Description: Sylvia 是一个热爱学习的女♂孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. Sylvia 所在的方阵中有n×m名学生,方阵的行数为 ...
- 【线段树合并】解题报告:luogu P4556雨天的尾巴 (树上对点差分 + 动态开点 + 线段树合并)线段树合并模板离线/在线详解
题目链接:雨天的尾巴 本题本身是一个非常简单的一道树上差分的模板题,但是由于变态的数据范围,我们直接用数组是存不下的(本来使用一颗普通的线段树直接维护最大值即可.但是本题的空间只有128MB,直接按照 ...
- 洛谷P3960 列队(动态开节点线段树)
题意 题目链接 Sol 看不懂splay..,看不懂树状数组... 只会暴力动态开节点线段树 观察之后不难发现,我们对于行和列需要支持的操作都是相同的:找到第\(k\)大的元素并删除,在末尾插入一个元 ...
- CF1045G AI robots(动态开点线段树)
题意 火星上有$N$个机器人排成一行,第$i$个机器人的位置为$x_{i}$,视野为$r_{i}$,智商为$q_{i}$.我们认为第$i$个机器人可以看到的位置是$[x_{i}-r_{i},x_{i} ...
- 树链剖分(bzoj 1036: [ZJOI2008]树的统计Count)
树链剖分: 把一棵树剖分为若干条链,然后利用数据结构(树状数组,SBT,Splay,线段树等等)去维护每一条链,复杂度 为O(logn),总体复杂度O(nlog²n) 步骤: ①将树的边分成重边和轻边 ...
- codeforces 915E - Physical Education Lessons 动态开点线段树
题意: 最大$10^9$的区间, $3*10^5$次区间修改,每次操作后求整个区间的和 题解: 裸的动态开点线段树,计算清楚数据范围是关键... 经过尝试 $2*10^7$会$MLE$ $10^7$会 ...
- HDU 6681 Rikka with Cake(扫描线、动态开点线段树)
http://acm.hdu.edu.cn/showproblem.php?pid=6681 题意 在矩形区域内有k条射线,问这些射线将矩形分成了多少区域 题解 容易发现答案为所有射线交点个数+1. ...
最新文章
- 人生低谷时的锅底法则
- python文件和目录操作方法
- MySQL性能优化之必备技能【推荐】
- 未正确安装master data services_GP数据库安装
- mysql all语法怎么用_MySQL UNION 与 UNION ALL 语法与用法
- Android应用开发—Application
- 初探Bootstrap
- 游戏开发筑基之控制台光标定位(C语言)
- 深入了解-微信开发者工具
- 二级python有必要买书吗_清华大学出版社-图书详情-《二级Python编程指南》
- java jsp 404错误页面模板_JSP页面404错,点击分页的按钮就报错
- Disk for DB is too low. Cassandra state detected DOWN. Disk space for DB not retrievable
- 【Python学习向】 图片去水印
- 实体链指(2)EL:Disambiguation-Only
- CCS安装失败的原因
- 通俗理解OvO与OvR
- ECCV 2022 | 视觉新任务!AVS:视听分割
- 多功能噪音消除器支持多种场景模式
- 程序员惨遭996,注册Github域名炮轰996工作模式,半小时破千星
- 因为在清除过期缓存条目后可用空间仍不足 - 请考虑增加缓存的最大空间。