【洛谷 P4116】 Qtree3 (树链剖分)
题目链接
树剖练手题,想复习下树剖。
第一次提交\(T\)成QQC
看我
???
看了数据范围的确挺恶心的,我的复杂度是\(O(Mlog^2N)\)的,数据范围有三段
For 1/3 of the test cases, N=5000, Q=400000.
For 1/3 of the test cases, N=10000, Q=300000.
For 1/3 of the test cases, N=100000, Q=100000.
很极限就对了。难道是我常数太大了?那也不至于只对\(3\)个点吧。
我看了一下,原来我求\(size\)的时候没有加上子树的\(size\)...这样就会剖出假的重链。
我加上去,再交,还是\(T\)成QQC。
看我
......
原来是标记\(top\)的时候错了。改过来就\(A\)了。
虽然有两个细节错误,但是没有别的错误,也就是说我树剖大致模板和线段树都是一次写对的。。
话不多说。
树剖后用线段树来维护,维护最小值,黑点的值为\(dfs\)序,白点的值为\(INF\),每次查询找到链上的最小值即为答案。
因为从\(1\)到\(x\)是一条直链,越上的点也就是越靠近\(1\)的点,\(dfs\)序一定最小。
#include <cstdio>
#define INF 2147483647
#define re register
int s; char ch;
inline int read(){
s = 0; ch = getchar();
while(ch < '0' || ch > '9') ch = getchar();
while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); }
return s;
}
inline int min(int a, int b){
return a > b ? b : a;
}
const int MAXN = 100010;
struct Edge{
int next, to;
}e[MAXN << 1];
int head[MAXN], num, n, m, a, b, w[MAXN];
inline void Add(int from, int to){
e[++num].to = to; e[num].next = head[from]; head[from] = num;
e[++num].to = from; e[num].next = head[to]; head[to] = num;
}
int dep[MAXN], size[MAXN], maxson[MAXN], top[MAXN], ID, dfn[MAXN], pos[MAXN], f[MAXN];
namespace SegTree{
#define left (now << 1)
#define right (now << 1 | 1)
int Min[MAXN << 2];
inline void pushup(int now){
Min[now] = min(Min[left], Min[right]);
}
void build(int now, int l, int r){
if(l == r){ Min[now] = INF; return; }
int mid = (l + r) >> 1;
build(left, l, mid);
build(right, mid + 1, r);
pushup(now);
}
void update(int now, int l, int r, int x){
if(l == r){ Min[now] = (w[pos[x]] ? x : INF); return; }
int mid = (l + r) >> 1;
if(x <= mid) update(left, l, mid, x);
else update(right, mid + 1, r, x);
pushup(now);
}
int query(int now, int l, int r, int wl, int wr){
if(l > wr || r < wl) return INF;
if(l >= wl && r <= wr) return Min[now];
int ans = INF, mid = (l + r) >> 1;
ans = min(ans, query(left, l, mid, wl, wr));
ans = min(ans, query(right, mid + 1, r, wl, wr));
return ans;
}
}using namespace SegTree;
void dfs1(int u, int fa){
size[u] = 1; f[u] = fa;
for(re int i = head[u]; i; i = e[i].next)
if(e[i].to != fa){
dfs1(e[i].to, u);
size[u] += size[e[i].to];
if(size[e[i].to] > size[maxson[u]])
maxson[u] = e[i].to;
}
}
void dfs2(int u, int rt){
dfn[u] = ++ID; pos[ID] = u; top[u] = rt;
if(maxson[u]) dfs2(maxson[u], rt);
for(re int i = head[u]; i; i = e[i].next)
if(e[i].to != f[u] && e[i].to != maxson[u])
dfs2(e[i].to, e[i].to);
}
inline int solve(int u){
int ans = INF;
while(top[u] != 1){
ans = min(ans, query(1, 1, n, dfn[top[u]], dfn[u]));
u = f[top[u]];
}
ans = min(ans, query(1, 1, n, dfn[1], dfn[u]));
return ans == INF ? -1 : pos[ans];
}
int main(){
n = read(); m = read();
for(re int i = 1; i < n; ++i)
Add(read(), read());
dfs1(1, 0);
dfs2(1, 1);
build(1, 1, n);
for(re int i = 1; i <= m; ++i){
a = read(); b = read();
if(!a){
w[b] ^= 1;
update(1, 1, n, dfn[b]);
}
else printf("%d\n", solve(b));
}
return 0;
}
【洛谷 P4116】 Qtree3 (树链剖分)的更多相关文章
- 洛谷P3979 遥远的国度 树链剖分+分类讨论
题意:给出一棵树,这棵树每个点有权值,然后有3种操作.操作一:修改树根为rt,操作二:修改u到v路径上点权值为w,操作三:询问以rt为根x子树的最小权值. 解法:如果没有修改树根操作那么这题就是树链剖 ...
- 洛谷 P4114 Qtree1 树链剖分
目录 题面 题目链接 题目描述 输入输出格式 输入格式: 输出格式: 输入输出样例 输入样例: 输出样例: 说明 说明 思路 Change Query AC代码 总结 题面 题目链接 P4114 Qt ...
- [洛谷P3384] [模板] 树链剖分
题目传送门 显然是一道模板题. 然而索引出现了错误,狂wa不止. 感谢神犇Dr_J指正.%%%orz. 建线段树的时候,第44行. 把sum[p]=bv[pos[l]]%mod;打成了sum[p]=b ...
- 洛谷.4114.Qtree1(树链剖分)
题目链接 模板题都错了这么多次.. //边权赋到点上 树剖模板 //注意LCA.链的顶端不能统计到答案! #include <cstdio> #include <cctype> ...
- 洛谷3384&bzoj1036树链剖分
值得注意的是: 一个点的子树是存在一起的...也就是说我们修改子树的时候只用... /********************************************************* ...
- 洛谷P4116 Qtree3
题目描述 给出\(N\)个点的一棵树(\(N-1\)条边),节点有白有黑,初始全为白 有两种操作: \(0\) \(i\) : 改变某点的颜色(原来是黑的变白,原来是白的变黑) \(1\) \(v\) ...
- 洛谷P4116 Qtree3(树剖+线段树)
传送门 LCT秒天秒地 树剖比较裸的题了 用线段树记录一下区间的最左边的黑点的编号(因为同一条链上肯定是最左边的深度最小,到根节点距离最近) 然后记得树剖的时候肯定是越后面的答案越优,因为深度越浅 / ...
- 洛谷 P4116 Qtree3
Qtree系列第三题 我是题面 读完题大概不难判断是一道树剖的题 这道题的关键是记录两种状态,以及黑点的序号(不是编号) 线段树啊当然 定义两个变量v,f,v表示距离根节点最近的黑点,默认-1,f则表 ...
- Qtree3 - 树链剖分
打完以后才发现写复杂了……算了懒得改了 #include <bits/stdc++.h> using namespace std; ],fa[][],size[],wson[],vis[] ...
- 洛谷 P3384 【模板】树链剖分
树链剖分 将一棵树的每个节点到它所有子节点中子树和(所包含的点的个数)最大的那个子节点的这条边标记为"重边". 将其他的边标记为"轻边". 若果一个非根节点的子 ...
随机推荐
- 《学习OpenCV》课后习题解答1
题目:(P104) 下面这个练习是帮助掌握矩阵类型.创造一个三通道二维矩阵,字节类型,大小为100*100,并设置所有数值为0. a.在矩阵中使用cvCircle( CvArr* img, CvPoi ...
- css滤镜让图片模糊
.mhblur { filter: url(blur.svg#blur); /* FireFox, Chrome, Opera */ -webkit-filter: blur(53px); /* Ch ...
- maven仓库中添加自定义的包jar包
mvn install:install-file -DgroupId=impl -DartifactId=center -Dversion=1.0 -Dpackaging=jar -Dfile=D:\ ...
- mysql 重置 root 密码
mysqld_safe --skip-grant-tables & UPDATE mysql.user SET authentication_string=PASSWORD('mima') W ...
- 配置和修改springboot默认国际化文件
SpringBoot默认国际化文件为:classpath:message.properties,如果放在其它文件夹中,则需要在application.properties配置属性spring.mess ...
- 【刷题】洛谷 P3809 【模板】后缀排序
题目背景 这是一道模板题. 题目描述 读入一个长度为 \(n\) 的由大小写英文字母或数字组成的字符串,请把这个字符串的所有非空后缀按字典序从小到大排序,然后按顺序输出后缀的第一个字符在原串中的位置. ...
- [BZOJ5120] [2017国家集训队测试]无限之环
Description 曾经有一款流行的游戏,叫做InfinityLoop,先来简单的介绍一下这个游戏: 游戏在一个n×m的网格状棋盘上进行,其中有些小方格中会有水管,水管可能在方格某些方向的边界的中 ...
- BZOJ2697 特技飞行 【贪心】
题目链接 BZOJ2697 题解 好水好水的贪心... 容易发现每种特技只表演两次,多表演没有意义,而且差距越长收益越大 然后就可以贪,最大的放两端,次大的往里,然后是第三大....... 证明很简单 ...
- mac, xcode 6.1 安装command line tools 支持,autoconf,automake等
以下软件包 都去我的环境库找到 1 先安装 tcl库 2 安装macports /opt/local/bin/port 一般装到这里 安装autoconf时提示: Warning: The Xcode ...
- foo.prototype作为新对象的原型来使用
最近在研究js,疑惑也比较多.主要是被原型这个东西给弄迷糊了.疑惑出自于: function foo { this.name = 'foo'; } alert(foo.prototype === Fu ...