bzoj3531: [Sdoi2014]旅行 (树链剖分 && 动态开点线段树)
感觉动态开点线段树空间复杂度好优秀呀
树剖裸题
把每个宗教都开一颗线段树就可以了
但是我一直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]旅行 (树链剖分 && 动态开点线段树)的更多相关文章
- 【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) ...
- BZOJ 3531 [Sdoi2014]旅行 树链剖分+动态开点线段树
题意 S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰. 为了方便,我们用 ...
- [bzoj 3531][SDOI2014]旅行(树链剖分+动态开点线段树)
题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3531 分析: 对于每个颜色(颜色<=10^5)都建立一颗线段树 什么!那么不是M ...
- 洛谷P3313 [SDOI2014]旅行(树链剖分 动态开节点线段树)
题意 题目链接 Sol 树链剖分板子 + 动态开节点线段树板子 #include<bits/stdc++.h> #define Pair pair<int, int> #def ...
- [ZJOI2019]语言(树链剖分+动态开点线段树+启发式合并)
首先,对于从每个点出发的路径,答案一定是过这个点的路径所覆盖的点数.然后可以做树上差分,对每个点记录路径产生总贡献,然后做一个树剖维护,对每个点维护一个动态开点线段树.最后再从根节点开始做一遍dfs, ...
- 【BZOJ3531】[Sdoi2014]旅行 树链剖分+动态开点线段树
[BZOJ3531][Sdoi2014]旅行 Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天 ...
- bzoj3531——树链剖分+动态开点线段树
3531: [Sdoi2014]旅行 Time Limit: 20 Sec Memory Limit: 512 MB Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连 ...
- BZOJ4999: This Problem Is Too Simple!树链剖分+动态开点线段树
题目大意:将某个节点的颜色变为x,查询i,j路径上多少个颜色为x的点... 其实最开始一看就是主席树+树状数组+DFS序...但是过不去...MLE+TLE BY FCWWW 其实树剖裸的一批...只 ...
- [LuoguU41039]PION后缀自动机 树链剖分+动态开点线段树
链接 刚开始看出题人题解都吓蒙掉了,还以为是什么难题,结果就一板子题 思路:对每一个文件名开一棵线段树,然后树剖即可 #include<bits/stdc++.h> #define REP ...
随机推荐
- 2020.02.01【NOIP提高组】模拟B 组总结反思——数列(sequence) 树 【2012东莞市选】时间流逝 挖掘机技术哪家强
T1 数列(sequence) 比赛时 我自以为是地打了简简单单一个判断--- 之后 Waiting-- T2 2753. 树(tree) 比赛时 这题我居然比赛时也想了很久,可能是因为我太懒,我很早 ...
- Apache Tomcat配置启动
文章目录 前提 配置启动Tomcat 遇到的问题 端口被占用 解决方案 淇℃伅 特别感谢 前提 已经安装Java JDK 已经配置将Java JDK的bin目录添加至环境变量Path 已经配置JAVA ...
- ASP.NET MVC5 的请求管道和运行生命周期
https://www.jianshu.com/p/848fda7f79e0 请求处理管道 请求管道是一些用于处理HTTP请求的模块组合,在ASP.NET中,请求管道有两个核心组件:IHttpModu ...
- [BOI2003] Gem - 树形dp
结论 不同颜色数不会超过 \(O(\log n)\) 然后就是很简单的树形dp了 顺便复习一下树形dp怎么写 #include <bits/stdc++.h> using namespac ...
- 在IIS中配置申请的SSL证书
第一步,右键服务器证书=>打开功能 第二步,右侧选择导入,将申请到的证书按窗体内容导入即可 第三步,右键需要加载证书的网站,选择编辑绑定=>类型选择https=>选择刚才导入的数字证 ...
- Appium appium 通过 adb 无线连接 Android 真机
一.准备工作 1.准备一台或多台Android设备(如小米,华为),开启USB调试2.Android设备与电脑(Mac或者Windows)在同一个局域网内3.电脑安装好ADB工具 二.具体步骤 1.使 ...
- 未安装Oracle数据库,使用PL\SQL Developer连接远程数据库解决方案
使用PL/SQL远程连接Oracle服务器 背景:本地未安装oracle数据库服务器,希望远程连接Oracle服务器 1.下载oracle数据库客户端 下载64位windows的instantclie ...
- I+Me=完整的自我
这是这个系列的第二篇文章,如同第一篇一样,这篇文章会在24小时后删除. 之所以如此极端,因为我自认为这篇文章很有价值,不以这种方式,大家即使看了,也只会一带而过,不会真的汲取到营养. 这篇文章涉及的关 ...
- .NET知识梳理——4.特性Attribute
1. 特性 1.1 特性Attribute 特性就是一个类,继承自Attribute抽象类(该类无抽象方法.避免实例化),约定俗成用Attribute类结尾,标记时可省略掉Attribu ...
- Python基础教程-02
<Python基础教程> 第3章 使用字符串 字符串方法find返回的并非布尔值.如果find像这样返回0,就意味着它在索引0处找到 了指定的子串 join可合并一个字符串列表,不能合并数 ...