CF1137F Matches Are Not a Child's Play
我们定义一棵树的删除序列为:每一次将树中编号最小的叶子删掉,将该节点编号加入到当前序列的最末端,最后只剩下一个节点时将该节点的编号加入到结尾。现在给出一棵n个节点的树,有m次操作:
up v:将v号节点的编号变为当前所有节点编号的\(max + 1\)
when v:查询v在当前树的删除序列中是第几号元素
compare u v:查询u和v在当前树的删除序列中谁更靠前
题解
考虑每个点up后会带来什么影响。
可以发现新修改的这个点和修改这个点之前编号最大的点之间的这条链是最后被删掉的。
而且删除的顺序是有序的。
把这条链删掉之后,其他的链之间的删除顺序是不变的。
所以我们可以考虑维护这些链。
如果每次令最大的点为根,那么每次的操作相当于是\(makeroot\)。
这里我们还需要给每条链赋一个权值,为删除顺序当中的优先度,这个可以在\(LCT\)上打标记。
还有一个问题就是如何维护一开始的删除序列。
这个其实\(dfs\)一遍就可以了,先令每个点的权值为自己的编号,然后自底向上更新,如果儿子的比父亲的大就用儿子去更新父亲。
代码
#include<bits/stdc++.h>
#define N 200009
#define ls ch[x][0]
#define rs ch[x][1]
using namespace std;
typedef long long ll;
char s[10];
int ch[N][2],fa[N],n,q,head[N],tot,size[N],col[N],now,rev[N],maxn;
inline ll rd(){
ll x=0;char c=getchar();bool f=0;
while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return f?-x:x;
}
struct edge{
int n,to;
}e[N<<1];
struct BIT{
int tr[N<<1];
inline void add(int x,int y){while(x<=maxn)tr[x]+=y,x+=x&-x;}//!!!!!!!!!!
inline int query(int x){int ans=0;while(x)ans+=tr[x],x-=x&-x;return ans;}
}tr;
inline bool ge(int x){return ch[fa[x]][1]==x;}
inline bool isroot(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
inline void pushup(int x){size[x]=size[ls]+size[rs]+1;}
inline void rotate(int x){
int y=fa[x],o=ge(x);
ch[y][o]=ch[x][o^1];fa[ch[y][o]]=y;
if(!isroot(y))ch[fa[y]][ge(y)]=x;fa[x]=fa[y];
fa[y]=x;ch[x][o^1]=y;
pushup(y);pushup(x);
}
inline void pushdown(int x){
if(rev[x]){
rev[ls]^=1;rev[rs]^=1;
rev[x]^=1;
swap(ls,rs);
}
if(ls)col[ls]=col[x];///!!!!!
if(rs)col[rs]=col[x];
}
inline void _pushdown(int x){
if(!isroot(x))_pushdown(fa[x]);
pushdown(x);
}
inline void splay(int x){
_pushdown(x);
while(!isroot(x)){
int y=fa[x];
if(isroot(y))rotate(x);
else rotate(ge(x)==ge(y)?y:x),rotate(x);
}
}
inline void access(int x){
for(int y=0;x;y=x,x=fa[x]){
splay(x);
tr.add(col[x],-size[x]+size[rs]);
tr.add(now,size[x]-size[rs]);
ch[x][1]=y;pushup(x);
}
}
inline void makeroot(int x){
++now;
access(x);splay(x);rev[x]^=1;col[x]=now;
}
inline void add(int u,int v){
e[++tot].n=head[u];e[tot].to=v;head[u]=tot;
}
int query(int x){
splay(x);
return tr.query(col[x]-1)+size[rs]+1;
}
void dfs(int u){
col[u]=u;
size[u]=1;
for(int i=head[u];i;i=e[i].n)if(e[i].to!=fa[u]){
int v=e[i].to;fa[v]=u;
dfs(v);
if(col[v]>col[u]){
col[u]=col[v];
ch[u][1]=v;
size[u]=size[v]+1;
}
}
tr.add(col[u],1);
}
int main(){
n=rd();q=rd();
maxn=n+q;
int u,v,w;
now=n;
for(int i=1;i<n;++i){
u=rd();v=rd();
add(u,v);add(v,u);
}
dfs(n);
while(q--){
scanf("%s",s);
if(s[0]=='u'){
u=rd();
makeroot(u);
}
else if(s[0]=='w'){
u=rd();
printf("%d\n",query(u));
}
else if(s[0]=='c'){
u=rd();v=rd();
printf("%d\n",query(u)>query(v)?v:u);
}
}
return 0;
}
CF1137F Matches Are Not a Child's Play的更多相关文章
- CF1137F Matches Are Not a Child's Play(LCT思维题)
题目 CF1137F 很有意思的题目 做法 直接考虑带修改的做法,上一次最大值为u,这次修改v,则最大值为v了 我们发现:\(u-v\)这条链会留到最后,序列里的其他元素相对位置不变,这条链会\(u\ ...
- CF1137F Matches Are Not a Child's Play(树链剖分)
题面 我们定义一棵树的删除序列为:每一次将树中编号最小的叶子删掉,将该节点编号加入到当前序列的最末端,最后只剩下一个节点时将该节点的编号加入到结尾. 例如对于上图中的树,它的删除序列为:2 4 3 1 ...
- 【树链剖分 ODT】cf1137F. Matches Are Not a Child's Play
孔爷的杂题系列:LCT清新题/ODT模板题 题目大意 定义一颗无根树的燃烧序列为:每次选取编号最小的叶子节点形成的序列. 要求支持操作:查询一个点$u$在燃烧序列中的排名:将一个点的编号变成最大 $n ...
- [cf1137F]Matches Are Not a Child's Pla
显然compare操作可以通过两次when操作实现,以下仅考虑前两种操作 为了方便,将优先级最高的节点作为根,显然根最后才会被删除 接下来,不断找到剩下的节点中(包括根)优先级最高的节点,将其到其所在 ...
- [Codeforces1137F]Matches Are Not a Child's Play——LCT+树状数组
题目链接: [Codeforces1137F]Matches Are Not a Child's Play 题目大意: 我们定义一棵树的删除序列为:每一次将树中编号最小的叶子删掉,将该节点编号加入到当 ...
- Codeforces 1137F Matches Are Not a Child's Play [LCT]
Codeforces 很好,通过这题对LCT的理解又深了一层. 思路 (有人说这是套路题,然而我没有见过/kk) 首先发现,删点可以从根那里往下删,非常难受,所以把权值最大的点提为根. 然后考虑\(x ...
- Codeforces 1137F - Matches Are Not a Child's Play(LCT)
Codeforces 题面传送门 & 洛谷题面传送门 考虑将一个点 \(x\) 的编号变为当前所有点编号最大值 \(+1\) 会对每个点的删除时间产生怎么样的影响.由于编号最大的点肯定是最后一 ...
- LCT[Link-Cut-Tree学习笔记]
部分摘抄于 FlashHu candy99 所以文章篇幅较长 请有足够的耐心(不是 其实不用学好splay再学LCT的-/kk (至少现在我平衡树靠fhq) 如果学splay的话- 也许我菜吧-LCT ...
- 多校联训 DS 专题
CF1039D You Are Given a Tree 容易发现,当 \(k\) 不断增大时,答案不断减小,且 \(k\) 的答案不超过 \(\lfloor\frac {n}{k}\rfloor\) ...
随机推荐
- centos 6.5 升级openssh-7.5
1.环境 2.安装telnet 服务,防止ssh升级之后登陆不上服务器,使用telnet 连接服务器 yum install telnet-server -y chkconfig telnet on ...
- [USACO 2008 Jan. Silver]架设电话线 —— 最短路+二分
一道图论的最短路题.一开始连最短路都没想到,可能是做的题太少了吧,完全没有思路. 题目大意: FJ的农场周围分布着N根电话线杆,任意两根电话线杆间都没有电话线相连.一共P对电话线杆间可以拉电话线,第i ...
- TensorFlow学习笔记8-深度学习的正则化
深度学习的正则化 回顾一些基本概念 概念 描述 设计矩阵 数据集在特征向量上的表示 训练误差 学习到的模型与训练集标签之间的误差 泛化误差(测试误差) 学习到的模型与测试集之间的误差 欠拟合 模型的训 ...
- js 获取屏幕宽高
网页可见区域宽: document.body.clientWidth 网页可见区域高: document.body.clientHeight 网页可见区域宽: document.body.offset ...
- C++期末
华侨大学 面向对象程序设计(二) 试卷(A) 系别 计算机.软件工程.网络工程08 考试日期 2009年 06月29日 姓名 学号 成绩 一.选择题 (20分,每小题2分) ()关于重载函数在调用时匹 ...
- STL关联式容器之set\map ----以STL源码为例
关联式容器的特征:所用元素都会根据元素的键值自动被排序. set STL 中的关联式容器低层数据结构为红黑树,其功能都是调用低层数据结构中提供的相应接口. set元的元素不会像map那样同时拥有键(k ...
- 通过FSDataOutputStream向HDFS上写数据
FSDataOutputStream,这个类重载了很多write方法,用于写入很多类型的数据:比如字节数组,long,int,char等等. 像FSDataInputStream一样,要获得FSDat ...
- vue 运行时报 dependency was not found:错误
这种报错我知道的有两种情况引起: 第一种: 是在引入文件的时候路径不对, 解决办法是: 只要在加一个./就行了: import test from './test' 改成先对路径 如果是安装的模块的话 ...
- [集合]java中的 可变参数
可变的参数类型,也称为不定参数类型.英文缩写是varargus,还原一下就是variable argument type.通过它的名字可以很直接地看出来,这个方法在接收参数的时候,个数是不定的. pu ...
- ASE Backend Alpha Sprint Review
[Backend] Alpha Review展示博客 团队成员介绍:仅限于Alpha阶段有贡献的成员. 典型场景描述:描述并说明你们认为的产品面向的典型场景. 团队管理与协作:包括但不限于团队内部如何 ...