正题

题目链接:https://www.luogu.com.cn/problem/CF1137F


题目大意

给出\(n\)个点的一棵树,第\(i\)个点权值为\(i\)。

一棵树的删除序列定义为每次删除编号最小的叶子并将其加入序列末尾。

要求支持

  1. 修改一个点的权值为一个比目前所有权值都要大的一个值
  2. 询问一个点在删除序列的位置
  3. 询问两个点在删除序列的先后顺序

\(1\leq n,q\leq 2\times 10^5\)


解题思路

假设我们已经确定的先后顺序,目前最大的权值为\(y\)号点,然后修改一个点\(x\)时相当于把\(y\sim x\)的路径上所有点依次放在序列末尾。

相当于我们要支持提出一条树链,可以考虑用\(LCT\)实现。

以权值最大的点为根,我们对于每一条树链(splay)附上同一个颜色,那么一个点的答案就是颜色编号比它小的点数+所在树链上深度比它小的点数+1。

然后修改就相当于连接+换根+换颜色。颜色方面可以用树状数组维护前缀和,然后再\(Access\)的时候进行修改,换根也是可以用\(LCT\)做到的。

时间复杂度\(O(n\log^2 n)\)


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
#define lowbit(x) (x&-x)
using namespace std;
const int N=2e5+10;
struct node{
int to,next;
}a[N<<1];
int n,q,cnt,tot,ls[N],col[N];
struct BinaryInTree{
int t[N<<1],n;
void Change(int x,int val){
while(x<=n){
t[x]+=val;
x+=lowbit(x);
}
return;
}
int Ask(int x){
int ans=0;
while(x){
ans+=t[x];
x-=lowbit(x);
}
return ans;
}
}B;
struct LCT{
int fa[N],t[N][2],siz[N];
bool r[N];stack<int> s;
bool Nroot(int x)
{return fa[x]&&(t[fa[x]][0]==x||t[fa[x]][1]==x);}
bool Direct(int x)
{return t[fa[x]][1]==x;}
void PushUp(int x)
{siz[x]=siz[t[x][0]]+siz[t[x][1]]+1;return;}
void Rev(int x)
{r[x]^=1;swap(t[x][0],t[x][1]);return;}
void PushDown(int x){
if(t[x][0])col[t[x][0]]=col[x];
if(t[x][1])col[t[x][1]]=col[x];
if(!r[x])return;
Rev(t[x][0]);Rev(t[x][1]);
r[x]=0;return;
}
void Rotate(int x){
int y=fa[x],z=fa[y];
int xs=Direct(x),ys=Direct(y);
int w=t[x][xs^1];
if(Nroot(y))t[z][ys]=x;
t[y][xs]=w;t[x][xs^1]=y;
if(w)fa[w]=y;fa[y]=x;fa[x]=z;
PushUp(y);PushUp(x);return;
}
void Splay(int x){
int y=x;s.push(x);
while(Nroot(y))y=fa[y],s.push(y);
while(!s.empty())PushDown(s.top()),s.pop();
while(Nroot(x)){
int y=fa[x];
if(!Nroot(y))Rotate(x);
else if(Direct(x)==Direct(y))
Rotate(y),Rotate(x);
else Rotate(x),Rotate(x);
}
return;
}
void Access(int x){
for(int y=0;x;y=x,x=fa[x]){
Splay(x);t[x][1]=0;PushUp(x);
B.Change(col[x],-siz[x]);
B.Change(cnt,siz[x]);
t[x][1]=y;PushUp(x);
}
return;
}
void MakeRoot(int x){
++cnt;Access(x);
Splay(x);col[x]=cnt;
Rev(x);return;
}
int Ask(int x){
Splay(x);
return siz[t[x][1]]+1+B.Ask(col[x]-1);
}
}T;
void addl(int x,int y){
a[++tot].to=y;
a[tot].next=ls[x];
ls[x]=tot;return;
}
void dfs(int x){
col[x]=x;
for(int i=ls[x];i;i=a[i].next){
int y=a[i].to;
if(y==T.fa[x])continue;
T.fa[y]=x;dfs(y);
if(col[y]>col[x]){
col[x]=col[y];
T.t[x][1]=y;
}
}
B.Change(col[x],1);
T.PushUp(x);
}
int main()
{
scanf("%d%d",&n,&q);
for(int i=1;i<n;i++){
int x,y;
scanf("%d%d",&x,&y);
addl(x,y);addl(y,x);
}
B.n=n+q;cnt=n;dfs(n);
for(int i=1;i<=q;i++){
char op[6];int x,y;
scanf("%s%d",op,&x);
if(op[0]=='u')T.MakeRoot(x);
else if(op[0]=='w')
printf("%d\n",T.Ask(x));
else if(op[0]=='c'){
scanf("%d",&y);
int l=T.Ask(x),r=T.Ask(y);
if(l<r)printf("%d\n",x);
else printf("%d\n",y);
}
}
return 0;
}

CF1137F-Matches Are Not a Child‘s Play【LCT】的更多相关文章

  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. Codeforces 1137F - Matches Are Not a Child's Play(LCT)

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

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

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

  8. 【CF438E】The Child and Binary Tree(多项式运算,生成函数)

    [CF438E]The Child and Binary Tree(多项式运算,生成函数) 题面 有一个大小为\(n\)的集合\(S\) 问所有点权都在集合中,并且点权之和分别为\([0,m]\)的二 ...

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

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

随机推荐

  1. (一)响应式web设计。。。freecodecamp笔记

    HTML基础 HTML 的全称是 HyperText Markup Language(超文本标记语言),它是一种用来描述网页结构的标记语言. h1用作主标题,h2用作副标题,还有h3.h4.h5.h6 ...

  2. Lambda Expressions and Functional Interfaces: Tips and Best Practices

    转载自https://www.baeldung.com/java-8-lambda-expressions-tips 1. Overview   Now that Java 8 has reached ...

  3. flink双流join

    package com.streamingjoin import org.apache.flink.api.common.state.{ValueState, ValueStateDescriptor ...

  4. python实现两台不同主机之间进行通信(客户端和服务端)——Socket

    大家好,我是辰哥~ 今天教大家通过Python进行Socket网络编程 (做一个聊天程序) 可以实现在不同的主机(电脑)之间进行通话. 具体效果如何,接着往下看 可以看到客户端(上方)向服务器端(下方 ...

  5. promise小案例

    页面中有个板块,需要多张图片加载完之后才能进行显示 //页面中有个板块 需要多张图片加载完之后才能进行显示 const loadImg = (src) => { return new Promi ...

  6. IT项目经理-成长手记学习笔记

    无论多难,都要记住一点,只要别人不赶你走,你就厚着脸皮待下去,这样你才有可能熬到项目成功. 项目经理要管事,更要管人. 项目计划->职责分工->确定项目范围 遇事及时处理,当场处理,处理错 ...

  7. SpringBoot笔记(2)

    一.容器功能 1.1 组件添加 1. @Configuration Full模式:获取对象时,首先在容器内搜索是否存在,如存在直接拿出 默认为Full模式,单例 配置类组件之间有依赖关系,方法会被调用 ...

  8. 面试必备:排序算法汇总(c++实现)

    排序算法主要考点: 7种排序 冒泡排序.选择排序.插入排序.shell排序.堆排序.快速排序.归并排序 以上排序算法是面试官经常会问到的算法,至于其他排序比如基数排序等等,这里不列举. 以下算法通过c ...

  9. Shell中常用的语句

    exit 完全中断脚本的执行 break 中断脚本的循环,但是会执行循环外的语句 continue 跳出本次循环,进行下一次循环 进一步了解三者的区别,有如下实验: 执行该脚本: 脚本正常运行情况: ...

  10. Kubernetes 组件简介

    关于Kubernetes是什么??? Kubernetes是致力于提供跨主机集群的自动部署.扩展.高可用以及运行应用程序容器的平台. Kubernets集群组成有哪些??? k8s由master和no ...