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

up v:将v号节点的编号变为当前所有节点编号的\(max + 1\)

when v:查询v在当前树的删除序列中是第几号元素

compare u v:查询u和v在当前树的删除序列中谁更靠前

题解

考虑每个点up后会带来什么影响。

可以发现新修改的这个点和修改这个点之前编号最大的点之间的这条链是最后被删掉的。

而且删除的顺序是有序的。

把这条链删掉之后,其他的链之间的删除顺序是不变的。

所以我们可以考虑维护这些链。

如果每次令最大的点为根,那么每次的操作相当于是\(makeroot\)。

这里我们还需要给每条链赋一个权值,为删除顺序当中的优先度,这个可以在\(LCT\)上打标记。

还有一个问题就是如何维护一开始的删除序列。

这个其实\(dfs\)一遍就可以了,先令每个点的权值为自己的编号,然后自底向上更新,如果儿子的比父亲的大就用儿子去更新父亲。

代码

  1. #include<bits/stdc++.h>
  2. #define N 200009
  3. #define ls ch[x][0]
  4. #define rs ch[x][1]
  5. using namespace std;
  6. typedef long long ll;
  7. char s[10];
  8. int ch[N][2],fa[N],n,q,head[N],tot,size[N],col[N],now,rev[N],maxn;
  9. inline ll rd(){
  10. ll x=0;char c=getchar();bool f=0;
  11. while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
  12. while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
  13. return f?-x:x;
  14. }
  15. struct edge{
  16. int n,to;
  17. }e[N<<1];
  18. struct BIT{
  19. int tr[N<<1];
  20. inline void add(int x,int y){while(x<=maxn)tr[x]+=y,x+=x&-x;}//!!!!!!!!!!
  21. inline int query(int x){int ans=0;while(x)ans+=tr[x],x-=x&-x;return ans;}
  22. }tr;
  23. inline bool ge(int x){return ch[fa[x]][1]==x;}
  24. inline bool isroot(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
  25. inline void pushup(int x){size[x]=size[ls]+size[rs]+1;}
  26. inline void rotate(int x){
  27. int y=fa[x],o=ge(x);
  28. ch[y][o]=ch[x][o^1];fa[ch[y][o]]=y;
  29. if(!isroot(y))ch[fa[y]][ge(y)]=x;fa[x]=fa[y];
  30. fa[y]=x;ch[x][o^1]=y;
  31. pushup(y);pushup(x);
  32. }
  33. inline void pushdown(int x){
  34. if(rev[x]){
  35. rev[ls]^=1;rev[rs]^=1;
  36. rev[x]^=1;
  37. swap(ls,rs);
  38. }
  39. if(ls)col[ls]=col[x];///!!!!!
  40. if(rs)col[rs]=col[x];
  41. }
  42. inline void _pushdown(int x){
  43. if(!isroot(x))_pushdown(fa[x]);
  44. pushdown(x);
  45. }
  46. inline void splay(int x){
  47. _pushdown(x);
  48. while(!isroot(x)){
  49. int y=fa[x];
  50. if(isroot(y))rotate(x);
  51. else rotate(ge(x)==ge(y)?y:x),rotate(x);
  52. }
  53. }
  54. inline void access(int x){
  55. for(int y=0;x;y=x,x=fa[x]){
  56. splay(x);
  57. tr.add(col[x],-size[x]+size[rs]);
  58. tr.add(now,size[x]-size[rs]);
  59. ch[x][1]=y;pushup(x);
  60. }
  61. }
  62. inline void makeroot(int x){
  63. ++now;
  64. access(x);splay(x);rev[x]^=1;col[x]=now;
  65. }
  66. inline void add(int u,int v){
  67. e[++tot].n=head[u];e[tot].to=v;head[u]=tot;
  68. }
  69. int query(int x){
  70. splay(x);
  71. return tr.query(col[x]-1)+size[rs]+1;
  72. }
  73. void dfs(int u){
  74. col[u]=u;
  75. size[u]=1;
  76. for(int i=head[u];i;i=e[i].n)if(e[i].to!=fa[u]){
  77. int v=e[i].to;fa[v]=u;
  78. dfs(v);
  79. if(col[v]>col[u]){
  80. col[u]=col[v];
  81. ch[u][1]=v;
  82. size[u]=size[v]+1;
  83. }
  84. }
  85. tr.add(col[u],1);
  86. }
  87. int main(){
  88. n=rd();q=rd();
  89. maxn=n+q;
  90. int u,v,w;
  91. now=n;
  92. for(int i=1;i<n;++i){
  93. u=rd();v=rd();
  94. add(u,v);add(v,u);
  95. }
  96. dfs(n);
  97. while(q--){
  98. scanf("%s",s);
  99. if(s[0]=='u'){
  100. u=rd();
  101. makeroot(u);
  102. }
  103. else if(s[0]=='w'){
  104. u=rd();
  105. printf("%d\n",query(u));
  106. }
  107. else if(s[0]=='c'){
  108. u=rd();v=rd();
  109. printf("%d\n",query(u)>query(v)?v:u);
  110. }
  111. }
  112. return 0;
  113. }

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 Pla

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

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

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

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

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

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

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

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

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

  9. 多校联训 DS 专题

    CF1039D You Are Given a Tree 容易发现,当 \(k\) 不断增大时,答案不断减小,且 \(k\) 的答案不超过 \(\lfloor\frac {n}{k}\rfloor\) ...

随机推荐

  1. tensorflow和keras的安装

    1 卸载tensorflow方法,在终端输入:  把protobuf删除了才能卸载干净. sudo pip uninstall protobuf sudo pip uninstall tensorfl ...

  2. c#处理bin文件

    1. fs.Position  写入的位置,从哪个位置开始写 fs.Write(byte1,0,byte1.Length); byte1写入的byte[], 写入内容从第几位开始取,length取多长 ...

  3. 实验报告2&&第四周课程总结

    实验报告: 写一个名为Rectangle的类表示矩形.其属性包括宽width.高height和颜色color,width和height都是double型的,而color则是String类型的.要求该类 ...

  4. HDFS镜像文件fsimage和编辑日志文件edits

    镜像文件和编辑日志文件 1)概念 namenode被格式化之后,将在/opt/module/hadoop-2.7.2/data/tmp/dfs/name/current目录中产生如下文件 edits_ ...

  5. 懵圈了,面试官问一个 TCP 连接可发多少个 HTTP 请求?

    作者:松若章 https://zhuanlan.zhihu.com/p/61423830 一道经典的面试题是从 URL 在浏览器被被输入到页面展现的过程中发生了什么,大多数回答都是说请求响应之后 DO ...

  6. BZOJ 1100 &&luogu 3454(计算几何+KMP)

    题面 给定一个多边形,求对称轴数量. 分析 初看这似乎是一道计算几何的题目,但是如果暴力枚举对称轴,再去判断对称轴两边的边和角是否相等,时间复杂度为\(O(n^2)\),显然会TLE 问题转换 顺时针 ...

  7. sde自动备份到文件gdb

    本方法原理是使用python(以下简称py)调用arcmap的gp,在上再用bat调用py的方式实现.优点是能应用于所有数据库类型(包括pg,oracle等)的sde库 环境:arcmap 10.4, ...

  8. python数据结构:numpy

    一. numpy概述 numpy(Numerical Python)提供了python对多维数组对象ndarray(应该是N-dimension array)的支持,具有矢量运算能力,快速.节省空间. ...

  9. NodeJS、npm安装步骤和配置(windows版本)

    https://jingyan.baidu.com/article/48b37f8dd141b41a646488bc.html 上面这个链接很详细了,怕它没了自己记一遍.我的简洁一点. 1. 打开no ...

  10. struts2 中的 addActionError 、addFieldError、addActionMessage方法的区别添加错误信息

    转自:https://www.cnblogs.com/wangyp/archive/2011/07/13/2104828.html 一.addActionError("错误内容") ...