以最后被删去的点为根,这样子不会存在从父亲然后删掉某个点,儿子的删除顺序一定比父亲前。

记每个点子树中的最大值为 \(f_x\),那么一个点的排名,首先就需要加上 \(<f_x\) 的所有值,记对应 \(f_x\) 的点为 \(y\),那么 \(y\) 一定会一路上来删掉 \(x\)。

所以一个点排名就是 \(<f_x\) 的所有值,再加上 \(x,y\) 之间的距离。

考虑如何维护修改,设上一个根是 \(rt\),新根是 \(x\),那么等价于一次换根,需要将 \(x\) 到 \(rt\) 这条路径 cover 上 \(p_{rt}\),同时改掉 \(x\) 的值。

可以使用 ODT + 树剖维护。

Code
const int N=2e5+5;
int n,m;
vi G[N];
int dep[N],siz[N],top[N],son[N],dfn[N],fat[N],dfc,p[N*2],rp[N*2];
void dfs1(int u,int fa) {
dep[u]=dep[fa]+1,siz[u]=1,fat[u]=fa;
for(int v:G[u]) if(v!=fa) {
dfs1(v,u),siz[u]+=siz[v];
p[u]=max(p[u],p[v]);
if(siz[son[u]]<siz[v]) son[u]=v;
}
}
void dfs2(int u,int tp,int fa) {
top[u]=tp,dfn[u]=++dfc;
if(son[u]==0) return;
dfs2(son[u],tp,u);
for(int v:G[u]) if(v!=fa&&v!=son[u]) dfs2(v,v,u);
}
int bit[2*N];
void add(int x,int v) { for(;x<=n+m;x+=(x&-x)) bit[x]+=v; }
int ask(int x) { int ret=0; for(;x;x-=(x&-x)) ret+=bit[x]; return ret; }
struct node {
int l,r,v;
node() {}
node(int L,int R,int V) { l=L,r=R,v=V; }
bool operator < (const node &a) const { return l<a.l; }
};
set<node> odt;
auto spilt(int p) {
auto it=odt.lower_bound(node(p,-1,0));
if(it!=odt.end()&&it->l==p) return it;
--it;
int l=it->l,r=it->r,v=it->v;
odt.erase(it),odt.insert(node(l,p-1,v));
return odt.insert(node(p,r,v)).fi;
}
void cover(int l,int r,int v) {
auto itr=spilt(r+1),itl=spilt(l);
for(auto it=itl;it!=itr;it=odt.erase(it)) add(it->v,-((it->r)-(it->l)+1));
add(v,r-l+1),odt.insert(node(l,r,v));
}
void update(int u,int v,int w) {
while(top[u]!=top[v]) {
if(dep[top[u]]<dep[top[v]]) swap(u,v);
cover(dfn[top[u]],dfn[u],w),u=fat[top[u]];
}
if(dep[u]>dep[v]) swap(u,v);
cover(dfn[u],dfn[v],w);
}
int lca(int u,int v) {
while(top[u]!=top[v]) {
if(dep[top[u]]<dep[top[v]]) swap(u,v);
u=fat[top[u]];
}
return dep[u]<dep[v]?u:v;
}
int dist(int u,int v) { return dep[u]+dep[v]-2*dep[lca(u,v)]+1; }
int query(int x) {
auto pos=odt.upper_bound(node(dfn[x],-1,0));
int val=prev(pos)->v;
return ask(val-1)+dist(x,rp[val]);
}
int main() {
n=read(),m=read();
FOR(i,1,n-1) {
int x=read(),y=read();
G[x].pb(y),G[y].pb(x);
}
FOR(i,1,n) p[i]=rp[i]=i;
int rt=n,mx=n;
dfs1(n,0),dfs2(n,n,0);
FOR(i,1,n) add(p[i],1),odt.insert(node(dfn[i],dfn[i],p[i]));
FOR(i,1,m) {
string ch; cin>>ch;
int u=read();
if(ch[0]=='1') {
if(u!=rt) update(rt,u,mx);
++mx,cover(dfn[u],dfn[u],mx),rp[mx]=rt=u;
}
else if(ch[0]=='2') printf("%d\n",query(u));
else { int v=read(); printf("%d\n",query(u)>query(v)?v:u);}
}
}

CF1137F Matches Are Not a Child's Play 题解的更多相关文章

  1. CF1137F Matches Are Not a Child's Play(LCT思维题)

    题目 CF1137F 很有意思的题目 做法 直接考虑带修改的做法,上一次最大值为u,这次修改v,则最大值为v了 我们发现:\(u-v\)这条链会留到最后,序列里的其他元素相对位置不变,这条链会\(u\ ...

  2. CF1137F Matches Are Not a Child's Play(树链剖分)

    题面 我们定义一棵树的删除序列为:每一次将树中编号最小的叶子删掉,将该节点编号加入到当前序列的最末端,最后只剩下一个节点时将该节点的编号加入到结尾. 例如对于上图中的树,它的删除序列为:2 4 3 1 ...

  3. 【树链剖分 ODT】cf1137F. Matches Are Not a Child's Play

    孔爷的杂题系列:LCT清新题/ODT模板题 题目大意 定义一颗无根树的燃烧序列为:每次选取编号最小的叶子节点形成的序列. 要求支持操作:查询一个点$u$在燃烧序列中的排名:将一个点的编号变成最大 $n ...

  4. CF1137F Matches Are Not a Child's Play

    我们定义一棵树的删除序列为:每一次将树中编号最小的叶子删掉,将该节点编号加入到当前序列的最末端,最后只剩下一个节点时将该节点的编号加入到结尾.现在给出一棵n个节点的树,有m次操作: up v:将v号节 ...

  5. [cf1137F]Matches Are Not a Child's Pla

    显然compare操作可以通过两次when操作实现,以下仅考虑前两种操作 为了方便,将优先级最高的节点作为根,显然根最后才会被删除 接下来,不断找到剩下的节点中(包括根)优先级最高的节点,将其到其所在 ...

  6. [Codeforces1137F]Matches Are Not a Child's Play——LCT+树状数组

    题目链接: [Codeforces1137F]Matches Are Not a Child's Play 题目大意: 我们定义一棵树的删除序列为:每一次将树中编号最小的叶子删掉,将该节点编号加入到当 ...

  7. Codeforces 1137F Matches Are Not a Child's Play [LCT]

    Codeforces 很好,通过这题对LCT的理解又深了一层. 思路 (有人说这是套路题,然而我没有见过/kk) 首先发现,删点可以从根那里往下删,非常难受,所以把权值最大的点提为根. 然后考虑\(x ...

  8. Codeforces 1137F - Matches Are Not a Child's Play(LCT)

    Codeforces 题面传送门 & 洛谷题面传送门 考虑将一个点 \(x\) 的编号变为当前所有点编号最大值 \(+1\) 会对每个点的删除时间产生怎么样的影响.由于编号最大的点肯定是最后一 ...

  9. The Child and Zoo 题解

    题目描述 Of course our child likes walking in a zoo. The zoo has n areas, that are numbered from 1 to n. ...

  10. LCT[Link-Cut-Tree学习笔记]

    部分摘抄于 FlashHu candy99 所以文章篇幅较长 请有足够的耐心(不是 其实不用学好splay再学LCT的-/kk (至少现在我平衡树靠fhq) 如果学splay的话- 也许我菜吧-LCT ...

随机推荐

  1. week_Last

    Andrew Ng 机器学习笔记 总结! 注:等下用xmind做一个树状图! 来回忆知识! 所以...树状图待补.... 最后,谢谢吴恩达老师!! 感谢吴恩达老师的无私付出!!

  2. JavaScript:变量的作用域,window对象,关键字var/let与function

    为什么要将这些内容放在一起,因为他们都跟初始化有关系,我们慢慢说吧. 我们在代码中,都会声明变量.函数和对象,然后由浏览器解释器(下面简称浏览器)执行: 我们还说过,变量和对象的内存结构: 那么,是什 ...

  3. 大数据 - DWM层 业务实现

    DWM 建表,需要看 DWS 需求. DWS 来自维度(访客.商品.地区.关键词),为了出最终的指标 ADS 需求指标 DWT 为什么实时数仓没有DWT,因为它是历史的聚集,累积结果,实时数仓中不需要 ...

  4. Proxmark3 Easy 如何流畅的在Linux中操作?

    前言 Proxmark3 Easy可谓是国内能买到的比较便宜的RFID卡防设备了,曾在部分hv中出现. Proxmark3 Easy是国内简化的一种设备,利用的是较早的Proxmark3的开源,基础的 ...

  5. CSP-S2022 游记

    Day 998244350 模拟赛场场被学弟吊打.最后几天写了一堆随机化乱搞题以及奇怪的搜索,都是 CSP 不曾考的玩意(书接下文). 点分治已经敲烂了.最后两场每场一个. Day 499122175 ...

  6. 【问题解决】Tomcat启动服务时提示Filter初始化或销毁出现java.lang.AbstractMethodError错误

    问题背景 最近在开发项目接口,基于SpringBoot 2.6.8,最终部署到外置Tomcat 8.5.85 下,开发过程中写了一个CookieFilter,实现javax.servlet.Filte ...

  7. 从0到1手把手教你实现vite系列--重写依赖请求路径,处理/@modules/vue引用

    前面以及写了三篇了,这是第四篇,等我写完就合并起来哦 这个是第一篇的链接:vite原理,创建项目,基础知识 这个是第二篇的链接Vite-中篇-通过服务访问静态资源以及重写请求路径 这个是第三篇的链接# ...

  8. U3D编辑器开发&粒子特效/动画预览器示例

    概述 U3D提供了一套拓展编辑器的接口,可以用于直接在编辑器非播放模式运行程序.常用于运行一些工具程序,例如资源管理.在做技能编辑器等工具程序时,也可以使用运行模式接口会比较简单(这样也方便开放游戏创 ...

  9. mongdb遭遇勒索,用备份进行数据恢复

    mongdb遭遇勒索,用备份进行数据恢复 1.背景: 某台MongoDB服务器,没有配置用户名密码,放到公网不到一天,遭到删库勒索 All your data is a backed up. You ...

  10. Linux基础介绍

    Linux基础介绍 一.运维的本质 运维:运行维护应用程序 岗位需求:自动化运维.DBA.docker+K8s 运维的本质: 1.尽可能保证应用程序24小时不间断运行 2.尽可能保证数据的安全 3.尽 ...