[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]< ...
随机推荐
- 高级设置电脑系统windows7防火墙出错代码0×6D9原因与解决技巧
高级设置windows防火墙能够更好的保护电脑系统安全,在电脑系统windows7设置过程中难免会遇到某些问题,有用户在安装MRGT后想要打开SNMP的161端口,但在打开高级安全windows防火墙 ...
- 手机WebApp是什么?
手机WebApp是基于HTML5+css3开发的,一次开发,可以兼容许多的平台(android/iphone),调用本地功能(比如照相),可以用phonegap去实现,所以,是一个趋势.相比每个平台定 ...
- Java 运动模糊
Java 运动模糊代码 想用Java 写个运动模糊的效果,无奈本人水平有限,国内也没找到资源,于是Google到了一个文档,特地分享出来! 本代码源自 http://www.jhlabs.com/ip ...
- 用jquery怎么删除<table>的一行
摘录网址:用jquery怎么删除<table>的一行 思路:获取<table>的一行,然后使用 remove() 方法删除之.实例演示如下: 1.HTML结构 <tabl ...
- linux_http协议
什么是http协议? 超文本传输协议 最流行www服务,是http协议的实现 ssh,nfs,rsync客户端(Client)和服务端(Server),C/S架构,局域网内部用,胖客户端 http协议 ...
- 如何导入css和js?
导入css <link rel="stylesheet" href="css路径" type="text/css"> 导入js, ...
- Android Studio 下获取debug sha1和md5
Open Android Studio Open Your Project Click on Gradle (From Right Side Panel, you will see Gradle Ba ...
- Python类的__getitem__和__setitem__特殊方法
class testsetandget: kk = {}; def __getitem__(self, key): return self.kk[key]; ...
- TensorFlow-相关 API(学习笔记 )
1.tf.nn.conv2d conv2d( input, filter, strides, padding, use_cudnn_on_gpu=True, data_format='NHWC', n ...
- Android util.Log 工具类
Android中的日志工具类是Log(android.util.Log),这个类中提供了如下5个方法来供我们打印日志. Log.v().用于打印那些最为琐碎的.意义最小的日志信息.对应级别verbos ...