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

树剖裸题

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

但是我一直TLE

然后调了一个小时

为什么呢

因为我 #define max(x, y) (x > y ? x : y)

看起来好像可以减少常数的样子

我也是这么想的(作死

事实上

ans = max(ans, query(x, y))

类似这种语句中

query(x, y)会计算两次

然后就GG了

这告诉我们还是好好用库里的函数吧

 #include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
const int N = + ;
const int M = + ;
#define isdigit(x) (x >= '0' && x <= '9') inline void read(int &ans) {
ans = ;
static char buf = getchar();
register int res = ;
for (; !isdigit(buf); buf = getchar())
if (buf == '-') res = -;
for (; isdigit(buf); buf = getchar())
ans = ans * + buf - '';
ans *= res;
} int tot, n, q;
int sz[N], hs[N], pos[N], fa[N], top[N], w[N], c[N], dep[N];
vector < int > E[N]; void dfs1(int x, int d, int f) {
dep[x] = d; fa[x] = f;
hs[x] = -; sz[x] = ;
int tmp = ;
for (int i = ; i < E[x].size(); i++) {
int u = E[x][i];
if (u == f) continue;
dfs1(u, d + , x);
sz[x] += sz[u];
if (tmp < sz[u])
tmp = sz[u], hs[x] = u;
}
} void dfs2(int x, int t) {
top[x] = t; pos[x] = ++tot;
if (hs[x] == -) return;
dfs2(hs[x], t);
for (int i = ; i < E[x].size(); i++)
if (E[x][i] != fa[x] && E[x][i] != hs[x])
dfs2(E[x][i], E[x][i]);
} int cnt;
int sum[M], maxn[M], ls[M], rs[M], root[N]; inline void pushUp(int o) {
maxn[o] = max(maxn[ls[o]], maxn[rs[o]]);
sum[o] = sum[ls[o]] + sum[rs[o]];
} void modify(int &o, int l, int r, int p, int c) {
if (!o) o = ++cnt;
if (l == r) {
sum[o] = maxn[o] = c;
return ;
}
int mid = l + r >> ;
if (p <= mid) modify(ls[o], l, mid, p, c);
else modify(rs[o], mid + , r, p, c);
pushUp(o);
} int querySum(int o, int l, int r, int L, int R) {
if (!o) return ;
if (l >= L && r <= R) return sum[o];
int mid = l + r >> , ans = ;
if (L <= mid) ans += querySum(ls[o], l, mid, L, R);
if (R > mid) ans += querySum(rs[o], mid + , r, L, R);
return ans;
} inline int querySum(int c, int x, int y) {
int f1 = top[x], f2 = top[y];
int ans = ;
while (f1 != f2) {
if (dep[f1] < dep[f2])
swap(x, y), swap(f1, f2);
ans += querySum(root[c], , n, pos[f1], pos[x]);
x = fa[f1]; f1 = top[x];
}
if (dep[x] > dep[y]) swap(x, y);
ans += querySum(root[c], , n, pos[x], pos[y]);
return ans;
} int queryMax(int o, int l, int r, int L, int R) {
if (!o) return ;
if (l >= L && r <= R) return maxn[o];
int mid = l + r >> , ans = ;
if (L <= mid) ans = max(ans, queryMax(ls[o], l, mid, L, R));
if (R > mid) ans = max(ans, queryMax(rs[o], mid + , r, L, R));
return ans;
} inline int queryMax(int c, int x, int y) {
int f1 = top[x], f2 = top[y];
int ans = ;
while (f1 != f2) {
if (dep[f1] < dep[f2])
swap(x, y), swap(f1, f2);
ans = max(ans, queryMax(root[c], , n, pos[f1], pos[x]));
x = fa[f1]; f1 = top[x];
}
if (dep[x] > dep[y]) swap(x, y);
ans = max(ans, queryMax(root[c], , n, pos[x], pos[y]));
return ans;
} int main() {
read(n); read(q);
for (int i = ; i <= n; i++)
read(w[i]), read(c[i]);
for (int i = ; i < n; i++) {
int u, v;
read(u); read(v);
E[u].push_back(v);
E[v].push_back(u);
}
dfs1(, , ); dfs2(, );
for (int i = ; i <= n; i++)
modify(root[c[i]], , n, pos[i], w[i]);
for (int i = ; i <= q; i++) {
char ch[]; scanf("%s", ch);
int x, y; read(x); read(y);
if (ch[] == 'C') {
if (ch[] == 'C') {
modify(root[c[x]], , n, pos[x], );
c[x] = y;
modify(root[y], , n, pos[x], w[x]);
}
else {
modify(root[c[x]], , n, pos[x], y);
w[x] = y;
}
}
else {
if (ch[] == 'S')
printf("%d\n", querySum(c[x], x, y));
else printf("%d\n", queryMax(c[x], x, y));
}
}
return ;
}

bzoj3531: [Sdoi2014]旅行 (树链剖分 && 动态开点线段树)的更多相关文章

  1. 【bzoj4999】This Problem Is Too Simple! 树链剖分+动态开点线段树

    题目描述 给您一颗树,每个节点有个初始值. 现在支持以下两种操作: 1. C i x(0<=x<2^31) 表示将i节点的值改为x. 2. Q i j x(0<=x<2^31) ...

  2. BZOJ 3531 [Sdoi2014]旅行 树链剖分+动态开点线段树

    题意 S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰. 为了方便,我们用 ...

  3. [bzoj 3531][SDOI2014]旅行(树链剖分+动态开点线段树)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3531 分析: 对于每个颜色(颜色<=10^5)都建立一颗线段树 什么!那么不是M ...

  4. 洛谷P3313 [SDOI2014]旅行(树链剖分 动态开节点线段树)

    题意 题目链接 Sol 树链剖分板子 + 动态开节点线段树板子 #include<bits/stdc++.h> #define Pair pair<int, int> #def ...

  5. [ZJOI2019]语言(树链剖分+动态开点线段树+启发式合并)

    首先,对于从每个点出发的路径,答案一定是过这个点的路径所覆盖的点数.然后可以做树上差分,对每个点记录路径产生总贡献,然后做一个树剖维护,对每个点维护一个动态开点线段树.最后再从根节点开始做一遍dfs, ...

  6. 【BZOJ3531】[Sdoi2014]旅行 树链剖分+动态开点线段树

    [BZOJ3531][Sdoi2014]旅行 Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天 ...

  7. bzoj3531——树链剖分+动态开点线段树

    3531: [Sdoi2014]旅行 Time Limit: 20 Sec  Memory Limit: 512 MB Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连 ...

  8. BZOJ4999: This Problem Is Too Simple!树链剖分+动态开点线段树

    题目大意:将某个节点的颜色变为x,查询i,j路径上多少个颜色为x的点... 其实最开始一看就是主席树+树状数组+DFS序...但是过不去...MLE+TLE BY FCWWW 其实树剖裸的一批...只 ...

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

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

随机推荐

  1. 详解 CUDA By Example 中的 Julia Set 绘制GPU优化

    笔者测试环境VS2019. 基本介绍 原书作者引入Julia Sets意在使用GPU加速图形的绘制.Julia Set 是指满足下式迭代收敛的复数集合 \[ Z_{n+1}=Z_{n}^2+C \] ...

  2. openlayers画区域

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

  3. AMCL论文及源码解析--参数(持续更新中)

    整理内容来自:http://wiki.ros.org/amcl 1.AMCL订阅的节点: scan (sensor_msgs/LaserScan):激光数据 tf (tf/tfMessage):各种转 ...

  4. Android View框架的layout机制

    概述 Android中View框架的工作机制中,主要有三个过程: 1.View树的测量(measure) Android View框架的measure机制 2.View树的布局(layout)Andr ...

  5. 题解 AT3718 【[ABC081B] Shift only】

    题目传送门 分析 直接暴力. 我们可以根据题意进行模拟,使用二重循环即可. 代码讲解 定义变量\(n\)和计数数组\(cnt\),再定义数组\(a\)并输入. int a[1000000]; int ...

  6. 深入浅出Mybatis系列五-TypeHandler简介及配置(mybatis源码篇)

    注:本文转载自南轲梦 注:博主 Chloneda:个人博客 | 博客园 | Github | Gitee | 知乎 上篇文章<深入浅出Mybatis系列(四)---配置详解之typeAliase ...

  7. hyper-v虚拟机不能访问外网的解决方案

    直接说解决方案,将虚拟机的一张网卡改为旧版网络适配器即可.具体原因还不可知. 延申一下,一般应该使用的交换机,是“外部”类型即可.

  8. DirectX11--HLSL语法入门

    前言 编写本内容仅仅是为了完善当前的教程体系,入门级别的内容其实基本上都是千篇一律,仅有一些必要细节上的扩充.要入门HLSL,只是掌握入门语法,即便把HLSL的全部语法也吃透了也并不代表你就能着色器代 ...

  9. http协议的POST传数据

    PostRequest使用StreamWriter对象写入请求流,不需要使用HttpUtility.UrlEncode显示转码,而下面的需要显示转码,还需要将参数转为字节码 蛋疼…………. publi ...

  10. 前后端分离开发,跨域时jsessionid每次请求都变化的问题解决方法

    本解决方法的使用前提是,前端开发使用的是vue,后端使用java(SpringMVC) 在前后端分离开发过程中,可能会出现因跨域而导致每次请求的jsessionid不一致的情况 解决方法: 前端:要在 ...