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. change or reset WSL password

    change or reset WSL password To change or reset your password, open the Linux distribution and enter ...

  2. pagelayout中边界灵敏度动画时间kv

    <PageLayoutWidget>: # 默认是50dp 设置边界 border:'100dp' # 默认哪一页 page:2 # 设置翻页动画及持续时间 anim_kwargs:{'d ...

  3. python打印爱心

    print('\n'.join([''.join([('AndyLove'[(x-y)%8]if((x*0.05)**2+(y*0.1)**2-1)**3-(x*0.05)**2*(y*0.1)**3 ...

  4. 使用vuex简单的实现系统中的状态管理

    最近项目中用到了vue,其中状态的集中管理使用到了vuex,因此就学习vuex做一个简单的记录.vuex的官方网址如下: https://vuex.vuejs.org/zh-cn/  vuex 当我们 ...

  5. 基于RequestBodyAdvice和ResponseBodyAdvice来实现spring中参数的加密和解密

    在日常开发中,有时候我们经常需要和第三方接口打交道,有时候是我们调用别人的第三方接口,有时候是别人在调用我们的第三方接口,那么为了调用接口的安全性,一般都会对传输的数据进行加密操作,如果每个接口都由我 ...

  6. 并发编程从零开始(九)-ConcurrentSkipListMap&Set

    并发编程从零开始(九)-ConcurrentSkipListMap&Set CAS知识点补充: 我们都知道在使用 CAS 也就是使用 compareAndSet(current,next)方法 ...

  7. 為什麼我的手機連Wi-Fi速度總是卡在75Mbps?Wi-Fi速度解惑~帶你一次看懂!

    正文字体大小:大 中 小 為什麼我的手機連Wi-Fi速度總是卡在75Mbps?Wi-Fi速度解惑-帶你一次看懂! (2017-02-21 10:57:48) 转载▼ 标签: wi-fi速度 手機wi- ...

  8. C++ string类型小结

    目录 构造函数 string.append() string.assign() string.at() string.back() string.begin() string.capasity() s ...

  9. 21.6.21 test

    \(NOI\) 模拟赛 字符串滚出 \(OI\) 看到题目名称,\(T1\) 串,\(T2\) 两个串,\(T3\) K个串,我 \(\cdots\),血压已经上来了. \(T1\) 写了 \(O(n ...

  10. c++继承关系中成员函数的重载、重写、重定义之间的区别

    1.Override.Overload.Redefine Overload 重载只能发生在类内部,不能发生在子类和父类的继承中.具体来说,如果子类中有父类同名.同返回值类型,但是不同参数列表,这两个在 ...