【洛谷 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 【模板】树链剖分
树链剖分 将一棵树的每个节点到它所有子节点中子树和(所包含的点的个数)最大的那个子节点的这条边标记为"重边". 将其他的边标记为"轻边". 若果一个非根节点的子 ...
随机推荐
- ALPHA-3
前言 失心疯病源3 团队代码管理github 站立会议 队名:PMS 530雨勤(组长) 今天完成了那些任务 16:00~20:18 援助行人模块并确定最终框架,顺便不死心的又找了一波车辆检测的dem ...
- iOS- AVSpeechSynthesizer——iOS7语音合成器
语音合成器的技术是iOS7推出的,可以实现无网络语音功能,支持多种语言 1. 定义一个成员变量,记录语音合成器 AVSpeechSynthesizer #import <AVFoundation ...
- 求csdn博客优良编辑方法
看见很多大牛的csdn博客编写的非常好,阅读体验也非常强.我就纳闷了,为啥我插公式也不行,插图片也不行呢... 插图片问题:图片不能复制招贴,否则在编辑的时候可以显示但是在发表之后就无法显示了.想要显 ...
- python json 序列化
如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML,但更好的方法是序列化为JSON,因为JSON表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过 ...
- java.awt.AWTError: Can't connect to X11 window server using ':20' as the value of the DISPLAY variable
1.使用pio在Linux服务器上创建window文件时,需要使用到Linux的图形界面服务,出现以下问题需确认用户权限. 参考文献:https://zhidao.baidu.com/question ...
- SpringBoot2.0(一) mybatis
使用mybatis springboot使用mybatis主要依赖 mybatis-spring-boot-starter 来实现.其提供了2中解决方案,一种是使用注解:另一种是简化后的传统的xml方 ...
- 创建udp服务端对象
DatagramSocket ds = null;//创建服务器对象 ds = new DatagramSocket(10001);//创建对象并指定端口 byte[] bytes = new byt ...
- Java 多线程序的一点理解
synchronized 是java 内主要的同步标记 1 同步非静态方法 作用域范围只是当前对象在不同线程间的同步, 如果n 为Test外的对象,在不同的Test对象之间,等于没有同步, 该方法只能 ...
- POJ3690:Constellations——题解
http://poj.org/problem?id=3690 题目大意:给一个图和几个子图,判断有多少种子图在原图出现过. —————————————————————— 二维哈希即可,操作看代码,我觉 ...
- 洛谷 P2272 [ZJOI2007]最大半连通子图 解题报告
P2272 [ZJOI2007]最大半连通子图 题目描述 一个有向图\(G=(V,E)\)称为半连通的\((Semi-Connected)\),如果满足:\(\forall u,v \in V\),满 ...