Codeforces 题面传送门 & 洛谷题面传送门

考虑将一个点 \(x\) 的编号变为当前所有点编号最大值 \(+1\) 会对每个点的删除时间产生怎么样的影响。由于编号最大的点肯定是最后一个被删除的,因此我们不妨令编号最大的点为根,那么可以发现,对于不在 \(x\) 到根这条路径上的点,它们删除的相对位置顺序是不会发生变化的,因为删除这样的点时,肯定它们的儿子已经被删除了,而它的父亲肯定没被删除,因此 \(x\) 到根节点这条路径上的点的删除顺序肯定不影响其它点的删除顺序,而由于此时 \(x\) 和原来的根节点 \(r\) 分别是所有点中,权值最大和第二大的点,因此 \(x\to r\) 中的点肯定是最后一批被删除的,并且删除顺序取决于它们与 \(r\) 的远近。

思考如何维护这个东西,发现这东西有点类似于 P3703 树点染色 的模型,修改一个点点权时,相当于将这个点先 access 一遍把 \(x\to r\) 这条链搞出来并赋成一个新的颜色,然后再 makeroot(x)。因此我们尝试用 LCT 维护这个东西,对于每个实链,我们给它一个优先值 \(v\),优先值越大表示这条链上的点越靠后被删除,而同一条实链上的点的删除顺序则是按照深度的增加而递减,因此考虑建一个 BIT,对于每种优先级 \(v\) 维护当前有多少个点的优先级为 \(v\),这样查询就做一遍前缀和,减掉当前实链中深度比当前节点小的点数,这个可以通过 LCT 的 \(siz\) 维护(注意,这里不需要写 top tree,因为是维护链的信息)。BIT 信息的维护就按照套路在 LCT 时扣掉除了右子树之外部分原来优先级的贡献,加上新贡献即可。

时间复杂度 \(n\log^2n\),别看 LCT 常数大,加上个 BIT 的小常数后倒跑得飞快(

const int MAXN=2e5;
int n,qu,hd[MAXN+5],to[MAXN*2+5],nxt[MAXN*2+5],ec=0,deg[MAXN+5];
void adde(int u,int v){to[++ec]=v;nxt[ec]=hd[u];hd[u]=ec;}
int t[MAXN*2+5],col_cnt=0;
void add(int x,int v){for(int i=x;i<=MAXN*2;i+=(i&(-i))) t[i]+=v;}
int query(int x){int ret=0;for(int i=x;i;i&=(i-1)) ret+=t[i];return ret;}
struct node{int ch[2],f,siz,rev_lz,col,col_lz;} s[MAXN+5];
void pushup(int k){s[k].siz=s[s[k].ch[0]].siz+s[s[k].ch[1]].siz+1;}
int ident(int k){return ((s[s[k].f].ch[0]==k)?0:((s[s[k].f].ch[1]==k)?1:-1));}
void connect(int k,int f,int op){s[k].f=f;if(~op) s[f].ch[op]=k;}
void rotate(int x){
int y=s[x].f,z=s[y].f,dx=ident(x),dy=ident(y);
connect(s[x].ch[dx^1],y,dx);connect(y,x,dx^1);connect(x,z,dy);
pushup(y);pushup(x);
}
void tag_rev(int k){swap(s[k].ch[0],s[k].ch[1]);s[k].rev_lz^=1;}
void tag_col(int k,int v){s[k].col_lz=v;s[k].col=v;}
void pushdown(int k){
if(s[k].rev_lz){
if(s[k].ch[0]) tag_rev(s[k].ch[0]);
if(s[k].ch[1]) tag_rev(s[k].ch[1]);
s[k].rev_lz=0;
} if(s[k].col_lz){
if(s[k].ch[0]) tag_col(s[k].ch[0],s[k].col_lz);
if(s[k].ch[1]) tag_col(s[k].ch[1],s[k].col_lz);
s[k].col_lz=0;
}
}
void pushall(int k){if(~ident(k)) pushall(s[k].f);pushdown(k);}
void splay(int k){
pushall(k);
while(~ident(k)){
if(ident(s[k].f)==-1) rotate(k);
else if(ident(s[k].f)==ident(k)) rotate(s[k].f),rotate(k);
else rotate(k),rotate(k);
}
}
void access(int k){
int pre=0;
for(;k;pre=k,k=s[k].f){
splay(k);
add(s[k].col,-s[k].siz+s[s[k].ch[1]].siz);
add(col_cnt,s[k].siz-s[s[k].ch[1]].siz);
s[k].ch[1]=pre;pushup(k);
}
}
void makeroot(int k){
col_cnt++;access(k);splay(k);
tag_rev(k);tag_col(k,col_cnt);
}
int ask(int k){splay(k);return query(s[k].col)-s[s[k].ch[0]].siz;}
void dfs0(int x,int f){
s[x].f=f;
for(int e=hd[x];e;e=nxt[e]){
int y=to[e];if(y==f) continue;
dfs0(y,x);
}
}
void calc(){
priority_queue<int,vector<int>,greater<int> > q;
for(int i=1;i<=n;i++) if(deg[i]==1) q.push(i);
while(!q.empty()){
int x=q.top();q.pop();col_cnt++;
add(col_cnt,1);s[x].col=col_cnt;
for(int e=hd[x];e;e=nxt[e]){
int y=to[e];
if((--deg[y])==1) q.push(y);
}
}
}
int main(){
scanf("%d%d",&n,&qu);for(int i=1;i<=n;i++) s[i].siz=1;
for(int i=1,u,v;i<n;i++) scanf("%d%d",&u,&v),deg[u]++,deg[v]++,adde(u,v),adde(v,u);
dfs0(n,0);calc();
while(qu--){
static char opt[13];scanf("%s",opt+1);
if(opt[1]=='u'){int x;scanf("%d",&x);makeroot(x);}
else if(opt[1]=='w'){int x;scanf("%d",&x);printf("%d\n",ask(x));}
else{
int u,v;scanf("%d%d",&u,&v);
printf("%d\n",(ask(u)<ask(v))?u:v);
}
// for(int i=1;i<=n;i++) printf("%d%c",ask(i)," \n"[i==n]);
}
return 0;
}

Codeforces 1137F - Matches Are Not a Child's Play(LCT)的更多相关文章

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

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

  2. Codeforces 1109F - Sasha and Algorithm of Silence's Sounds(LCT)

    Codeforces 题面传送门 & 洛谷题面传送门 讲个笑话,这题是 2020.10.13 dxm 讲题时的一道例题,而我刚好在一年后的今天,也就是 2021.10.13 学 LCT 时做到 ...

  3. Codeforces Round #394 (Div. 2) C.Dasha and Password(暴力)

    http://codeforces.com/contest/761/problem/C 题意:给出n个串,每个串的初始光标都位于0(列)处,怎样移动光标能够在凑出密码(每个串的光标位置表示一个密码的字 ...

  4. Codeforces Round #394 (Div. 2) E. Dasha and Puzzle(分形)

    E. Dasha and Puzzle time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  5. Codeforces Round #621 (Div. 1 + Div. 2)D dij(思维)

    题:https://codeforces.com/contest/1307/problem/D 题意:给定无向图,n为点,m为边.在给个k,为特殊点的数目,题目要求在这些特殊点上连一条边,让新图最短路 ...

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

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

  7. Codeforces Round #184 (Div. 2) E. Playing with String(博弈)

    题目大意 两个人轮流在一个字符串上删掉一个字符,没有字符可删的人输掉游戏 删字符的规则如下: 1. 每次从一个字符串中选取一个字符,它是一个长度至少为 3 的奇回文串的中心 2. 删掉该字符,同时,他 ...

  8. Codeforces Round #107 (Div. 1) B. Quantity of Strings(推算)

    http://codeforces.com/problemset/problem/150/B 题意: 给出n,m,k,n表示字符串的长度为n,m表示字符种类个数,k表示每k个数都必须是回文串,求满足要 ...

  9. Codeforces Round #332 (Div. 2) D. Spongebob and Squares(枚举)

    http://codeforces.com/problemset/problem/599/D 题意:给出一个数x,问你有多少个n*m的网格中有x个正方形,输出n和m的值. 思路: 易得公式为:$\su ...

随机推荐

  1. NX开发库版本问题

    有做NX二次开发的朋友经常问我这样的问题:我在NX8.0上开发的程序,可以在NX9.0上运行吗? 由于NX的开发库随着版本的更新也会不断更新,会增加新的方法,同时有些也会过时或者消失. 如下图:NX8 ...

  2. vue 2.0源码学习笔记—new Vue ( Vue 初始化过程 )

    new Vue(Vue 初始化) 一个vue实例化到底经历了什么?已下是博主自己的总结,不正确的地方请指出,谢谢~ 一.简述 从使用角度来看,挂载的顺序如下 1. $slots 2. $scopedS ...

  3. NC105 二分查找法

    二分查找(一) 二分查找看似简单,但是有很多的细节要注意. 题目是牛客NC105,找到有序数组中第一个大于或者等于所查找的数字. 初步写了如下的代码: class Solution { public: ...

  4. vue.$set实现原理

    上源码: export function set (target: Array<any> | Object, key: any, val: any): any { if (process. ...

  5. javascript-jquery插件

    1.jquery创建插件 jQuery.extend({插件名:函数体,插件名:函数体}): html部分 <div id="div1">开始动画</div> ...

  6. go-zero 实战之 blog 系统

    go-zero 实战项目:blog 本文以 blog 的网站后台为例,着重介绍一下如何使用 go-zero 开发 blog 的用户模块. 本文涉及的所有资料都已上传 github 仓库 kougazh ...

  7. Python课程笔记(六)

    今天上课补上了上次未学完比较重点的鼠标和键盘事件,同时开始学习运用turtle进行绘图. 本次课程的代码: https://gitee.com/wang_ming_er/python_course_l ...

  8. xmake v2.5.9 发布,改进 C++20 模块,并支持 Nim, Keil MDK 和 Unity Build

    xmake 是一个基于 Lua 的轻量级跨平台构建工具,使用 xmake.lua 维护项目构建,相比 makefile/CMakeLists.txt,配置语法更加简洁直观,对新手非常友好,短时间内就能 ...

  9. 手把手教你学Dapr - 3. 使用Dapr运行第一个.Net程序

    上一篇:手把手教你学Dapr - 2. 必须知道的概念 注意: 文章中提到的命令行工具即是Windows Terminal/PowerShell/cmd其中的一个,推荐使用Windows Termin ...

  10. redis 的主从模式哨兵模式

    原理理解 1,哨兵的作用就是检测redis主服务的状态,如果主服务器挂了,从服务就自动切换为主服务器,变为master.哨兵是一个独立的进程,作为进程,它会独立运行.其原理是哨兵通过发送命令,等待Re ...