参考了皎月半洒花的博客

看到树想到树剖,由于要取距自己到根离自己最近的标记点,刚开始想到线段树里存节点深度,查询时返回最大值。但是这样的话只能得到节点深度,无法得知节点编号,就想倍增乱搞一下,求出标记点,复杂度\(O(\log ^ {3}\;N)\)

虽然可以过但是实现有点复杂,就看了一下上面的博客

真的很强,由于树剖dfs时一条链上的编号是连续的,在此链中且深度越大线段树编号越大,所以我们可以在线段树里存当前节点的线段树编号,也达到了维护深度最大值的效果

答案就是ori [ (一条链中) MAX index] (ori为线段树编号回找树原始编号的数组)

复杂度\(O(\log ^ {2}\;N)\)

一直都是把树剖当板子用的,现在发现结合性质还有更多用处,我还要加油啊

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
int RD(){int out = 0,flag = 1;char c = getchar();while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();}while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();}return flag * out;}
const int maxn = 1000019,INF = 1e9;
int num,na,nume,cnt;
int head[maxn];
struct Node{int v,nxt;}E[maxn * 2];
void add(int u,int v){E[++nume].nxt = head[u];E[nume].v = v;head[u] = nume;}
int size[maxn],wson[maxn],dep[maxn],fa[maxn],top[maxn],pos[maxn],ori[maxn];
int v[maxn];
void dfs1(int id,int F){size[id] = 1;for(int i = head[id];i;i = E[i].nxt){int v = E[i].v;if(v == F)continue;dep[v] = dep[id] + 1;fa[v] = id;dfs1(v,id);size[id] += size[v];if(size[v] > size[wson[id]])wson[id] = v;}}
void dfs2(int id,int TP){top[id] = TP;pos[id] = ++cnt;ori[cnt] = id;if(!wson[id])return ;dfs2(wson[id],TP);for(int i = head[id];i;i = E[i].nxt){int v = E[i].v;if(v == fa[id] || v == wson[id])continue;dfs2(v,v);}}
#define lid (id << 1)
#define rid (id << 1) | 1
struct sag_tree{int l,r,max;}tree[maxn << 2];
void build(int id,int l,int r){tree[id].l = l;tree[id].r = r;if(l == r){tree[id].max = 0;return ;}int mid = (l + r) >> 1;build(lid,l,mid);build(rid,mid + 1,r);tree[id].max = max(tree[lid].max,tree[rid].max);}
void update(int id,int val, int l,int r){if(tree[id].l == l && tree[id].r == r){tree[id].max = l;return ;}int mid = (tree[id].l + tree[id].r) >> 1;if(mid < l)update(rid,val,l,r);else if(mid >= r)update(lid,val,l,r);else update(lid,val,l,mid),update(rid,val,mid + 1,r);tree[id].max = max(tree[lid].max,tree[rid].max);}
int query(int id,int l,int r){if(tree[id].l == l && tree[id].r == r)return tree[id].max;int mid = (tree[id].l + tree[id].r) >> 1;if(mid < l)return query(rid,l,r);else if(mid >= r)return query(lid,l,r);else return max(query(lid,l,mid),query(rid,mid + 1,r));}
void Qmax(int x, int y){int ans = 0;while(top[x] != top[y]){if(dep[top[x]] < dep[top[y]])swap(x, y);ans = query(1, pos[top[x]], pos[x]);if(ans){printf("%d\n", ori[ans]);return ;}x = fa[top[x]];}if(dep[x] > dep[y])swap(x, y);ans = query(1, pos[x], pos[y]);printf("%d\n", ori[ans]);}
int main(){num = RD();na = RD();for(int i = 1;i <= num - 1;i++){int u = RD(),v = RD();add(u,v),add(v,u);}dep[1] = 1;dfs1(1,-1);dfs2(1,1);build(1,1,num);update(1,pos[1],pos[1],pos[1]);for(int i = 1;i <= na;i++){char cmd;cin>>cmd;if(cmd == 'C'){int x = RD();update(1,pos[x],pos[x],pos[x]);}else{int x = RD();Qmax(x,1);}}return 0;}

转载于:https://www.cnblogs.com/Tony-Double-Sky/p/9285590.html

题解 P4092 【[HEOI2016/TJOI2016]树】相关推荐

  1. P2825 [HEOI2016/TJOI2016]游戏

    题目描述 详见  P2825 [HEOI2016/TJOI2016]游戏. solution 套路题. 一般思路是行列建点跑二分图最大匹配. 此题中的#会分隔行列,因此我们把每行的极大联通块设为点,列 ...

  2. [HEOI2016/TJOI2016]求和(第二类斯特林数)

    题目 [HEOI2016/TJOI2016]求和 关于斯特林数与反演的更多姿势\(\Longrightarrow\)点这里 做法 \[\begin{aligned}\\ Ans&=\sum\l ...

  3. 【题解】 [HEOI2016]排序题解 (二分答案,线段树)

    题目描述 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题,需要你来帮助他.这个难题是这样子的:给出一个1到n的全排列,现在对这个全排列序列进行 ...

  4. 主席树 + 后缀数组求LCP + 二分套二分 ---- P4094 [HEOI2016/TJOI2016]字符串

    题目链接 题目大意: 解题思路: 设我们的答案为midmidmid(注意这里有坑是[a,b][a,b][a,b]的所有子串和[c,d][c,d][c,d]这个子串的最长lcplcplcp),那么我们会 ...

  5. 线段树分裂与合并 ----- P2824 [HEOI2016/TJOI2016]排序 [线段树分裂合并 OR 01序列排序+二分线段树]

    题目链接 题目大意: 对一个序列,每次按照升序或者降序排序序列某一段,问你最后的序列是什么? 解法1:二分+线段树 首先我们知道对一个01序列进行排序是很快的!我们只要知道里面有多少个1和多少个0,那 ...

  6. BZOJ.4552.[HEOI2016/TJOI2016]排序(线段树合并/二分 线段树)

    题目链接 对于序列上每一段连续区间的数我们都可以动态开点建一棵值域线段树.初始时就是\(n\)棵. 对于每次操作,我们可以将\([l,r]\)的数分别从之前它所属的若干段区间中分离出来,合并. 对于升 ...

  7. [HEOI2016/TJOI2016]字符串 (后缀数组+主席树+二分)

    description 佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物.生日礼物放在一个神奇的箱子中.箱子外边写了一个长为 n 的字符串 s,和 m 个问题.佳媛姐姐必须正确回答这 m 个问 ...

  8. 洛谷P4094 [HEOI2016/TJOI2016]字符串【后缀数组+主席树+st表】

    时空限制 2000ms / 256MB 题目描述 佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物.生日礼物放在一个神奇的箱子中.箱子外边写了一个长为n的字符串s,和m个问题.佳媛姐姐必须正确 ...

  9. 洛谷 P4094 [HEOI2016/TJOI2016]字符串 后缀数组+二分+主席树

    题目链接 后缀数组 题目分析: sa[i] – 第i小的后缀的编号 rank[i] --编号为i的后缀排第几: height[i] – 第i和第i-1的最长lcp最长公共前缀: 1.二分答案,答案肯定 ...

最新文章

  1. Android核心分析之二十三Andoird GDI之基本原理及其总体框架
  2. 第12天续,CSS基础
  3. 程序异常是python语言基本控制结构_计算机二级python 知识点篇(程序的控制结构)...
  4. java实现图片验证码
  5. java for循环的这种写法怎么理解:for (; ; ) {},
  6. Consul初探-集成ocelot
  7. LeetCode 216. 组合总和 III(排列组合 回溯)
  8. WPF 虚拟化 VirtualizingWrapPanel 和 VirtualLizingTilePanel
  9. kafka结合mysql_logstash集成kafka,mysql实现数据采集
  10. java线程轮询_基于springboot实现轮询线程自动执行任务
  11. jdk1.8 HashMap ConcurrentHashMap
  12. python 读取wifi数据_通过Python实现WiFi测试数据分析
  13. [hadoop读书笔记] 第五章 MapReduce工作机制
  14. 算法:Merge k Sorted Lists(合并 k 个排序链表)
  15. 一个简单的MDX案例及说明 (转载)
  16. 图像超分辨率重建概述
  17. 彻底搞懂 python 中文乱码问题
  18. 既然选择了编程,只管风雨兼程
  19. 百度网盘下载限速解决
  20. STM32 芯片引脚的顺序说明

热门文章

  1. 卡方检验和卡方分布关联与区分
  2. C语言九键拼音,c语言--将中文转化为拼音
  3. IntelliJ配置在新开窗口打开项目
  4. 【C语言】关于我回头学的那些基础语法(一)
  5. 字体图标(iconfont)
  6. 找资料总结1553B总线协议知识和HI-1575数据手册
  7. 第5-1课:匈牙利算法与二分图的最大匹配
  8. 超频稳定测试软件,超频第三步:稳定性测试Kombuster
  9. 对人民的名字进行近义词分析
  10. SwiftUI 中的自定义导航