感觉动态开点线段树空间复杂度好优秀呀

树剖裸题

把每个宗教都开一颗线段树就可以了

但是我一直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]旅行 (树链剖分 动态开点线段树)相关推荐

  1. [LuoguU41039]PION后缀自动机 树链剖分+动态开点线段树

    链接 刚开始看出题人题解都吓蒙掉了,还以为是什么难题,结果就一板子题 思路:对每一个文件名开一棵线段树,然后树剖即可 #include<bits/stdc++.h> #define REP ...

  2. hdu3966 树链剖分点权模板+线段树区间更新/树状数组区间更新单点查询

    点权树的模板题,另外发现树状数组也是可以区间更新的.. 注意在对链进行操作时方向不要搞错 线段树版本 #include<bits/stdc++.h> using namespace std ...

  3. 动态开点线段树(多棵线段树)的内存分配与回收

    前言 线段树,是一个很好用的能支持O(logn)区间操作的数据结构,随着做一些稍微烦一点的题,有时候会发现有些情况要开一个数组的线段树,更有甚者要树套树,而在很多情况下线段树就不能把所有点都开满了(否 ...

  4. NOIP2017 列队——动态开点线段树

    Description: Sylvia 是一个热爱学习的女♂孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. Sylvia 所在的方阵中有n×m名学生,方阵的行数为  ...

  5. 【线段树合并】解题报告:luogu P4556雨天的尾巴 (树上对点差分 + 动态开点 + 线段树合并)线段树合并模板离线/在线详解

    题目链接:雨天的尾巴 本题本身是一个非常简单的一道树上差分的模板题,但是由于变态的数据范围,我们直接用数组是存不下的(本来使用一颗普通的线段树直接维护最大值即可.但是本题的空间只有128MB,直接按照 ...

  6. 洛谷P3960 列队(动态开节点线段树)

    题意 题目链接 Sol 看不懂splay..,看不懂树状数组... 只会暴力动态开节点线段树 观察之后不难发现,我们对于行和列需要支持的操作都是相同的:找到第\(k\)大的元素并删除,在末尾插入一个元 ...

  7. CF1045G AI robots(动态开点线段树)

    题意 火星上有$N$个机器人排成一行,第$i$个机器人的位置为$x_{i}$,视野为$r_{i}$,智商为$q_{i}$.我们认为第$i$个机器人可以看到的位置是$[x_{i}-r_{i},x_{i} ...

  8. 树链剖分(bzoj 1036: [ZJOI2008]树的统计Count)

    树链剖分: 把一棵树剖分为若干条链,然后利用数据结构(树状数组,SBT,Splay,线段树等等)去维护每一条链,复杂度 为O(logn),总体复杂度O(nlog²n) 步骤: ①将树的边分成重边和轻边 ...

  9. codeforces 915E - Physical Education Lessons 动态开点线段树

    题意: 最大$10^9$的区间, $3*10^5$次区间修改,每次操作后求整个区间的和 题解: 裸的动态开点线段树,计算清楚数据范围是关键... 经过尝试 $2*10^7$会$MLE$ $10^7$会 ...

  10. HDU 6681 Rikka with Cake(扫描线、动态开点线段树)

    http://acm.hdu.edu.cn/showproblem.php?pid=6681 题意 在矩形区域内有k条射线,问这些射线将矩形分成了多少区域 题解 容易发现答案为所有射线交点个数+1. ...

最新文章

  1. 人生低谷时的锅底法则
  2. python文件和目录操作方法
  3. MySQL性能优化之必备技能【推荐】
  4. 未正确安装master data services_GP数据库安装
  5. mysql all语法怎么用_MySQL UNION 与 UNION ALL 语法与用法
  6. Android应用开发—Application
  7. 初探Bootstrap
  8. 游戏开发筑基之控制台光标定位(C语言)
  9. 深入了解-微信开发者工具
  10. 二级python有必要买书吗_清华大学出版社-图书详情-《二级Python编程指南》
  11. java jsp 404错误页面模板_JSP页面404错,点击分页的按钮就报错
  12. Disk for DB is too low. Cassandra state detected DOWN. Disk space for DB not retrievable
  13. 【Python学习向】 图片去水印
  14. 实体链指(2)EL:Disambiguation-Only
  15. CCS安装失败的原因
  16. 通俗理解OvO与OvR
  17. ECCV 2022 | 视觉新任务!AVS:视听分割
  18. 多功能噪音消除器支持多种场景模式
  19. 程序员惨遭996,注册Github域名炮轰996工作模式,半小时破千星
  20. 因为在清除过期缓存条目后可用空间仍不足 - 请考虑增加缓存的最大空间。

热门文章

  1. hdu3397 线段树 成段更新
  2. 【最小割】HDU 4971 A simple brute force problem.
  3. 开放域对话中粗粒度响应选择的上下文细到粗蒸馏
  4. 面试AI岗,为什么我在100人中拿到了唯一年薪70万的offer?
  5. 历史文章之python
  6. 每日算法系列【LeetCode 128】最长连续序列
  7. NLP基础—3.文本表示
  8. python 用法 argparse.ArgumentParser()用法解析
  9. 常用Linux命令(持续更新)
  10. 2天玩转单反相机引领快乐光影新生活