[bzoj4551][Tjoi2016&Heoi2016]树-树链剖分
Brief Description
给定一颗有根树(根为1),有以下
两种操作:1. 标记操作:对某个结点打上标记(在最开始,只有结点1有标记,其他结点均无标记,而且对于某个
结点,可以打多次标记。)2. 询问操作:询问某个结点最近的一个打了标记的祖先(这个结点本身也算自己的祖
先)你能帮帮他吗?
Algorithm Design
树链剖分维护最深层带标记节点.
裸, 1A, 高兴.
Code
#include <cstdio>
#define init int l = t[k].l, r = t[k].r, mid = (l + r) >> 1
const int maxn = 201000;
int n, Q, cnt;
struct edge {
int to, next;
} e[maxn << 1];
struct seg {
int l, r, data;
} t[maxn << 2];
int head[maxn], q[maxn], bl[maxn], belong[maxn], size[maxn], dfn, like[maxn],
tag[maxn], fa[maxn], deep[maxn];
void add_edge(int u, int v) {
e[++cnt].to = v;
e[cnt].next = head[u];
head[u] = cnt;
}
void dfs1(int x) {
size[x] = 1;
for (int i = head[x]; i; i = e[i].next) {
if (e[i].to != fa[x]) {
fa[e[i].to] = x;
deep[e[i].to] = deep[x] + 1;
dfs1(e[i].to);
size[x] += size[e[i].to];
if (size[e[i].to] > size[like[x]])
like[x] = e[i].to;
}
}
}
void dfs2(int x, int chain) {
bl[x] = ++dfn;
q[dfn] = x;
belong[x] = chain;
if (like[x])
dfs2(like[x], chain);
for (int i = head[x]; i; i = e[i].next) {
if (e[i].to != fa[x] && e[i].to != like[x]) {
dfs2(e[i].to, e[i].to);
}
}
}
void build(int k, int l, int r) {
t[k].l = l, t[k].r = r, t[k].data = (l <= 1 && 1 <= r) ? 1 : 0;
if (l == r)
return;
int mid = (l + r) >> 1;
build(k << 1, l, mid);
build(k << 1 | 1, mid + 1, r);
}
void update(int k) {
t[k].data = t[k << 1 | 1].data ? t[k << 1 | 1].data : t[k << 1].data;
}
void modify(int k, int pos, int val) {
init;
if (l == r) {
if (deep[val] > deep[t[k].data])
t[k].data = val;
return;
}
if (pos <= mid)
modify(k << 1, pos, val);
else
modify(k << 1 | 1, pos, val);
update(k);
}
int query(int k, int x, int y) {
init;
if (x <= l && r <= y) {
return t[k].data;
}
int ans = 0;
if (x <= mid) {
int t = query(k << 1, x, y);
if (deep[t] > deep[ans])
ans = t;
}
if (y > mid) {
int t = query(k << 1 | 1, x, y);
if (deep[t] > deep[ans])
ans = t;
}
return ans;
}
void ask(int x, int f) {
int ans = 0;
while (belong[x] != belong[f]) {
int t = query(1, bl[belong[x]], bl[x]);
ans = t ? t : 0;
if (ans)
break;
x = fa[belong[x]];
}
int t = query(1, bl[belong[x]], bl[x]);
ans = t ? t : 0;
printf("%d\n", ans);
}
int main() {
#ifndef ONLINE_JUDGE
freopen("input", "r", stdin);
#endif
scanf("%d %d", &n, &Q);
deep[0] = -1;
for (int i = 1; i < n; i++) {
int x, y;
scanf("%d %d", &x, &y);
add_edge(x, y);
add_edge(y, x);
}
dfs1(1);
dfs2(1, 1);
build(1, 1, dfn);
while (Q--) {
char op[5];
scanf("%s", op);
if (op[0] == 'Q') {
int x;
scanf("%d", &x);
ask(x, 1);
} else {
int x;
scanf("%d", &x);
tag[x] = 1;
modify(1, bl[x], x);
}
}
}
[bzoj4551][Tjoi2016&Heoi2016]树-树链剖分的更多相关文章
- BZOJ4551[Tjoi2016&Heoi2016]树——dfs序+线段树/树链剖分+线段树
题目描述 在2016年,佳媛姐姐刚刚学习了树,非常开心.现在他想解决这样一个问题:给定一颗有根树(根为1),有以下 两种操作:1. 标记操作:对某个结点打上标记(在最开始,只有结点1有标记,其他结点均 ...
- [BZOJ4551][TJOI2016&&HEOI2016]树(并查集)
4551: [Tjoi2016&Heoi2016]树 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 1746 Solved: 800[Sub ...
- bzoj4553 [Tjoi2016&Heoi2016]序列 树状数组(区间最大值)+cqd
[Tjoi2016&Heoi2016]序列 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 1006 Solved: 464[Submit][ ...
- 线段树&数链剖分
傻逼线段树,傻逼数剖 线段树 定义: 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点. 使用线段树可以快速的查找某一个节点在若干条线段中出现 ...
- BZOJ4551 Tjoi2016&Heoi2016树(离线+并查集)
似乎是弱化的qtree3.树剖什么的非常无脑.考虑离线.并查集维护每个点的最近打标记祖先,倒序处理,删除标记时将其与父亲合并即可. #include<iostream> #include& ...
- BZOJ4551——[Tjoi2016&Heoi2016]树
1.题意: 给定一颗有根树(根为1),有以下 两种操作:1. 标记操作:对某个结点打上标记(在最开始,只有结点1有标记,其他结点均无标记,而且对于某个 结点,可以打多次标记.)2. 询问操作:询问某个 ...
- [bzoj4551][Tjoi2016][Heoi2016]树
Description 在2016年,佳媛姐姐刚刚学习了树,非常开心. 现在她想解决这样一个问题:给定一颗有根树(根为1),有以下两种操作: 1. 标记操作:对某个结点打上标记(在最开始,只有结点1有 ...
- BZOJ4551: [Tjoi2016&Heoi2016]树
Description 在2016年,佳媛姐姐刚刚学习了树,非常开心.现在他想解决这样一个问题:给定一颗有根树(根为1),有以下 两种操作:1. 标记操作:对某个结点打上标记(在最开始,只有结点1有标 ...
- BZOJ4553: [Tjoi2016&Heoi2016]序列 树套树优化DP
把pos[i]上出现的平常值定义为nor[i]最大值定义为max[i]最小值定义为min[i],那么我们发现在两个值,i(前),j(后),当且仅当max[i]<=nor[j],nor[i]< ...
随机推荐
- 流程控制语句if、else、elif、break、continue
1.控制流程 # if 判断语句 a = 12 if a>0: print('a大于0') if a<5: print('a大于5') else: print('哈哈哈') 2.基本形式: ...
- 汇编编译器(masm.exe)对jmp的相关处理
body, table{font-family: 微软雅黑; font-size: 13.5pt} table{border-collapse: collapse; border: solid gra ...
- express官网学习笔记
npm init 创建一个package.json npm install express --save-dev 安装到项目依赖 便于多人开发 路由结构定义 app.METHOD(PATH, HAND ...
- 机器学习-GBDT和XGboost
参考: 陈天奇slides : https://homes.cs.washington.edu/~tqchen/pdf/BoostedTree.pdf Friedman GBDT 论文: htt ...
- 长整形 Unix系统毫秒时间 (long类型) 转换为时间格式
/** * 把毫秒转化成日期 * * @param dateFormat(日期格式,例如:MM/ dd/yyyy HH:mm:ss) * @param millSec(毫秒数) * @return * ...
- SSH反向连接及Autossh
参考文章 http://www.freeoa.net/osuport/netmanage/autossh-useage-refer_2831.html 接触Linux恐怕对SSH再熟悉不过了,还有sc ...
- 常用Nagios配置命令
cd /usr/local/nagios/etc vim nagios.cfg /usr/local/nagios/bin/nagios -v /usr/local/nagios/etc/nagios ...
- 快速用Markdown排版一篇文章
前言 如果想先看下效果可以参见鄙人使用Markdown的排版的一篇文章--Markdown编辑效果. 本文会将每个设置在文内做示例. 本文不介绍完整的Markdown用法. 本文只简洁的介绍,使用Ma ...
- gulp最简示例
全局安装 $ npm gulp -g 作为项目的开发依赖安装 $ npm gulp --save-dev 脚本文件 在根目录创建gulpfile.js文件 const gulp = require(' ...
- Go笔记-流程控制
[if] if 是用于测试某个条件的语句,如果该条件(逻辑型或布尔型)成立,则会执行大括号内的代码,第一个大括号必须和if 或者else同行,否则非法 // 方式1 if condition { // ...