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]树-树链剖分的更多相关文章

  1. BZOJ4551[Tjoi2016&Heoi2016]树——dfs序+线段树/树链剖分+线段树

    题目描述 在2016年,佳媛姐姐刚刚学习了树,非常开心.现在他想解决这样一个问题:给定一颗有根树(根为1),有以下 两种操作:1. 标记操作:对某个结点打上标记(在最开始,只有结点1有标记,其他结点均 ...

  2. [BZOJ4551][TJOI2016&&HEOI2016]树(并查集)

    4551: [Tjoi2016&Heoi2016]树 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1746  Solved: 800[Sub ...

  3. bzoj4553 [Tjoi2016&Heoi2016]序列 树状数组(区间最大值)+cqd

    [Tjoi2016&Heoi2016]序列 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1006  Solved: 464[Submit][ ...

  4. 线段树&数链剖分

    傻逼线段树,傻逼数剖 线段树 定义: 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点. 使用线段树可以快速的查找某一个节点在若干条线段中出现 ...

  5. BZOJ4551 Tjoi2016&Heoi2016树(离线+并查集)

    似乎是弱化的qtree3.树剖什么的非常无脑.考虑离线.并查集维护每个点的最近打标记祖先,倒序处理,删除标记时将其与父亲合并即可. #include<iostream> #include& ...

  6. BZOJ4551——[Tjoi2016&Heoi2016]树

    1.题意: 给定一颗有根树(根为1),有以下 两种操作:1. 标记操作:对某个结点打上标记(在最开始,只有结点1有标记,其他结点均无标记,而且对于某个 结点,可以打多次标记.)2. 询问操作:询问某个 ...

  7. [bzoj4551][Tjoi2016][Heoi2016]树

    Description 在2016年,佳媛姐姐刚刚学习了树,非常开心. 现在她想解决这样一个问题:给定一颗有根树(根为1),有以下两种操作: 1. 标记操作:对某个结点打上标记(在最开始,只有结点1有 ...

  8. BZOJ4551: [Tjoi2016&Heoi2016]树

    Description 在2016年,佳媛姐姐刚刚学习了树,非常开心.现在他想解决这样一个问题:给定一颗有根树(根为1),有以下 两种操作:1. 标记操作:对某个结点打上标记(在最开始,只有结点1有标 ...

  9. BZOJ4553: [Tjoi2016&Heoi2016]序列 树套树优化DP

    把pos[i]上出现的平常值定义为nor[i]最大值定义为max[i]最小值定义为min[i],那么我们发现在两个值,i(前),j(后),当且仅当max[i]<=nor[j],nor[i]< ...

随机推荐

  1. sudo :apt-get:command not found

    在centos下用yum install xxx yum和apt-get的区别 一般来说著名的linux系统基本上分两大类:  1.RedHat系列:Redhat.Centos.Fedora等  2. ...

  2. hasResultError

    hasResultError 的作用是 让返回的对象可以报错误信息.

  3. lodash源码分析之缓存使用方式的进一步封装

    在世界上所有的民族之中,支配着他们的喜怒选择的并不是天性,而是他们的观点. --卢梭<社会与契约论> 本文为读 lodash 源码的第九篇,后续文章会更新到这个仓库中,欢迎 star:po ...

  4. MySql 修改外键 支持级联删除

    首先必须要有外键,InnoDB甚么的都不说了,直接上修改句子. 要先删除该外键,然后添加. 具体原因貌似是因为不支持alter外键的操作. ALTER TABLE `t_terminal` DROP ...

  5. java日志概述和原理

    OK,现在我们来研究下Java相关的日志. 日志记录是应用程序运行中必不可少的一部分.具有良好格式和完备信息的日志记录可以在程序出现问题时帮助开发人员迅速地定位错误的根源.对于开发人员来说,在程序中使 ...

  6. Linux安装JDK、MySQL和Tomcat

    1 依赖的安装 因为JDK.Tomcat和MySQL的安装过程中需要从网上下载部分支持包才可以继续,所以需要提前安装好依赖. yum install glibc.1686 yum -y install ...

  7. 面向对象_04【关键字:super使用】

    super关键字:解决当子类重写父类对象方法后,子类对象无法访问父类的成员1,调用父类成员变量和方法 super.成员变量 super.成员方法([参数1,参数2.......])Example: / ...

  8. Docker之镜像

    镜像(Images) 镜像是Docker的三大核心之一,类似于虚拟机,作用和虚拟机是一样的,唯独是组成部分会有些区别.简单的说如果我们想启动一个容器就必须要有镜像.docker运行容器前需要本地存在对 ...

  9. cat写入数据

    1.cat可以利用两个>>把内容追加到文件中 cat >>oldboy.txt<<EOF >1 >2 >EOF 会在文件中加入EOF中间的数据.E ...

  10. Redis服务启动失败,提示:redis-server:command not found

    今天我开始做主从复制的集群模式的测试,所以需要再装一个Linux操作系统,我在虚拟机里已经安装了一个Linux操作系统,Redis也已经配置好了.今天打算再安装一个Linux操作系统,Linux系统的 ...