https://www.luogu.org/problemnew/show/U18430

思路比较好想

树链剖分

对于1操作

  只需将以该点为根的子树打标记,将所有数存入数组排序

  每次进行1操作时,判断若该点已经被标记过,则操作无效

对于操作2

  在原树中求出lca,若lca被标记过,lca就是询问的两个点中

  编号较小的那个,lca值不改变

对于操作3

  若该点打过标记,输出该点与根的这条链上被打过标记的

  深度最小节点编号a与该节点编号的差+a的深度

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath> using namespace std;
const int N = 1e6 + ; #define yxy getchar()
#define lson jd << 1
#define rson jd << 1 | 1 int n, Q, now = , tim, w1, w2, w3;
int head[N], Num[N], deep[N], fa[N], lnum[N], rnum[N], son[N], topp[N], siz[N], tree[N], g_min[N << ];
struct Node{int u, v, nxt;} G[N << ]; inline int read(){
int x = ; char c = yxy;
while(c < '' || c > '') c = yxy;
while(c >= '' && c <= '') x = x * + c - '', c = yxy;
return x;
} inline void add(int u, int v){
G[now].u = u; G[now].v = v; G[now].nxt = head[u]; head[u] = now ++;
} void dfs_1(int u, int father, int dep){
fa[u] = father;
deep[u] = dep;
siz[u] = ;
for(int i = head[u]; ~ i; i = G[i].nxt){
int v = G[i].v;
if(v != father){
dfs_1(v, u, dep + );
siz[u] += siz[v];
if(siz[v] > siz[son[u]]) son[u] = v;
}
}
} void dfs_2(int u, int tp){
topp[u] = tp;
lnum[u] = ++ tim;
tree[u] = tim;
Num[tim] = u;
if(!son[u]) {rnum[u] = tim; return ;}
dfs_2(son[u], tp);
for(int i = head[u]; ~ i; i = G[i].nxt){
int v = G[i].v;
if(v != fa[u] && v != son[u]) dfs_2(v, v);
}
rnum[u] = tim;
} void Poi_A(int l, int r, int jd, int x){
if(l == r) {
if(g_min[jd]) w1 = ;
return ;
}
if(g_min[jd]) {
g_min[lson] = g_min[jd];
g_min[rson] = g_min[jd];
}
int mid = (l + r) >> ;
if(x <= mid) Poi_A(l, mid, lson, x);
else Poi_A(mid + , r, rson, x);
} void Sec_G(int l, int r, int jd, int x, int y, int yg){
if(x <= l && r <= y){
g_min[jd] = yg;
return ;
}
int mid = (l + r) >> ;
if(x <= mid) Sec_G(l, mid, lson, x, y, yg);
if(y > mid) Sec_G(mid + , r, rson, x, y, yg);
} int calc_lca(int x, int y){
int tp1 = topp[x], tp2 = topp[y];
while(tp1 != tp2){
if(deep[tp1] < deep[tp2]) swap(tp1, tp2), swap(x, y);
x = fa[tp1];
tp1 = topp[x];
}
return deep[x] > deep[y] ? y : x;
} void Sec_A(int l, int r, int jd, int x, int y){
if(x <= l && r <= y){
w2 = g_min[jd];
return ;
}
if(g_min[jd]) {
g_min[lson] = g_min[jd];
g_min[rson] = g_min[jd];
}
int mid = (l + r) >> ;
if(x <= mid) Sec_A(l, mid, lson, x, y);
if(y > mid) Sec_A(mid + , r, rson, x, y);
} int get_answer(int l, int r, int x){
int L = l, R = r, ret;
while(L <= R){
int mid = (L + R) >> ;
if(Num[mid] <= x) L = mid + , ret = mid;
else R = mid - ;
}
return ret - l;
} int main()
{
n = read(); Q = read();
for(int i = ; i <= n; i ++) head[i] = -;
for(int i = ; i < n; i ++) {
int u = read(), v = read();
add(u, v); add(v, u);
}
dfs_1(, , );
dfs_2(, );
while(Q --){
int opt = read();
if(opt == ){
int x = read();
if(!son[x]) continue ;
w1 = ;
Poi_A(, n, , tree[x]);
if(w1) continue ;
Sec_G(, n, , lnum[x], rnum[x], x);
sort(Num + lnum[x] + , Num + rnum[x] + );
}
else if(opt == ){
int x = read(), y = read();
int Lca_now = calc_lca(x, y);
w1 = ;
Poi_A(, n, , tree[Lca_now]);
if(w1) printf("%d\n", min(x, y));
else printf("%d\n", Lca_now);
}
else {
int x = read();
w1 = ;
Poi_A(, n, , tree[x]);
if(!w1) printf("%d\n", deep[x]);
else {
Sec_A(, n, , lnum[x], rnum[x]);
printf("%d\n", get_answer(lnum[w2], rnum[w2], x) + deep[w2]);
}
}
}
return ;
}

[Luogu] U18430 萌萌的大河的更多相关文章

  1. Luogu P4144 大河的序列 贪心+脑子

    首先向颜神犇致敬...还是自己太菜,又不仔细思考,上来就翻题解$qwq$ 首先有一种贪心方法:即,$ans=2*max(dirty_i)$ 证明:若现在的答案为$ans$,考虑一个新的数$x$对答案的 ...

  2. Luogu 魔法学院杯-第二弹(萌新的第一法blog)

    虽然有点久远  还是放一下吧. 传送门:https://www.luogu.org/contest/show?tid=754 第一题  沉迷游戏,伤感情 #include <queue> ...

  3. luogu p1268 树的重量——构造,真正考验编程能力

    题目链接:http://www.luogu.org/problem/show?pid=1268#sub -------- 这道题费了我不少心思= =其实思路和标称毫无差别,但是由于不习惯ACM风格的题 ...

  4. [luogu P2170] 选学霸(并查集+dp)

    题目传送门:https://www.luogu.org/problem/show?pid=2170 题目描述 老师想从N名学生中选M人当学霸,但有K对人实力相当,如果实力相当的人中,一部分被选上,另一 ...

  5. [luogu P2647] 最大收益(贪心+dp)

    题目传送门:https://www.luogu.org/problem/show?pid=2647 题目描述 现在你面前有n个物品,编号分别为1,2,3,--,n.你可以在这当中任意选择任意多个物品. ...

  6. Luogu 考前模拟Round. 1

    A.情书 题目:http://www.luogu.org/problem/show?pid=2264 赛中:sb题,直接暴力匹配就行了,注意一下读入和最后一句话的分句 赛后:卧槽 怎么只有40 B.小 ...

  7. luogu P2580 于是他错误的点名开始了

    luogu  P2580 于是他错误的点名开始了 https://www.luogu.org/problem/show?pid=2580 题目背景 XS中学化学竞赛组教练是一个酷爱炉石的人. 他会一边 ...

  8. html打造动画【系列1】- 萌萌的大白

    每个人心中都有一个暖暖的大白,blingbling的大眼睛~软软的肚子~宽厚的肩膀~善良的心肠~如果可以,我愿意沦陷在大白的肚子里永远不出来,哈哈~毛球要失宠咯~ 哈哈哈 每个人都是独立的个体,大白也 ...

  9. CJOJ 1331 【HNOI2011】数学作业 / Luogu 3216 【HNOI2011】数学作业 / HYSBZ 2326 数学作业(递推,矩阵)

    CJOJ 1331 [HNOI2011]数学作业 / Luogu 3216 [HNOI2011]数学作业 / HYSBZ 2326 数学作业(递推,矩阵) Description 小 C 数学成绩优异 ...

随机推荐

  1. Kubernetes 学习笔记(五):数据卷

    "数据卷"通常和"有状态"这个词同时出现,卷用于给有状态应用保存/共享状态. 常用的数据卷类型 1. emptyDir: 用于存储临时数据的空目录 emptyD ...

  2. php底层变量存储

    变量存储 php的变量使用一个结构体 zval来保存的,在Zend/zend.h中我们可以看到zval的定义 struct _zval_struct { /* Variable information ...

  3. WebSocket协议探究(二)

    一 复习和目标 1 复习 协议概述: WebSocket内置消息定界并且全双工通信 WebSocket使用HTTP进行协议协商,协商成功使用TCP连接进行传输数据 WebScoket数据格式支持二进制 ...

  4. 十、es6之扩展运算符 三个点(...)

    对象的扩展运算符 对象中的扩展运算符(...)用于取出参数对象中的所有可遍历属性,拷贝到当前对象之中 let bar = { a: 1, b: 2 }; let baz = { ...bar }; / ...

  5. java01_简介_开发环境

    JAVA的前世今生 美国SUN(Stanford University Network)公司,在中国大陆的正式中文名为"太阳计算机系统(中国)有限公司",在中国台湾的正式中文名为& ...

  6. 【前端】安装wampserver提示丢失MSVCR100.dll的解决方法

    先装Visual C++,再装wampserver 下载的时候请注意选择对应的32bit还是64bit的.然后安装. 再安装wamp

  7. Python练习_函数进阶_day10

    1. 1.作业 1,写函数,接收n个数字,求这些参数数字的和.(动态传参) 2,读代码,回答:代码中,打印出来的值a,b,c分别是什么?为什么? a=10 b=20 def test5(a,b): p ...

  8. 03 Django之视图函数

    一.Django的视图函数view 一个视图函数(类),简称视图,是一个简单的Python函数(类),它接受WEB请求并返回Web响应. 响应可以是一张网页的HTML内容,一个重定向,一个404错误, ...

  9. window.onload 和doucument.ready执行顺序

    浏览器渲染时 首先解析DOM结构 (同时在发送请求 去请求其他资源 比如图片 视频 等 ) DOM结构解析完毕 这个时候jQuery看准时机在这里添加了监听 所以Ready方法执行很早,可能会引起其他 ...

  10. 爬虫如何发现更多的url呢,怎么动态收集新的url连接

    大家在做爬虫采集数据的时候很多都会遇到增量采集的问题,有些时候是通过过滤url来进行的,有些是通过爬取网页后再进行分析判断, 以上这些过程也许大部分做爬虫的都会这么做,各位有没有想过, 除了以上的常用 ...