显然compare操作可以通过两次when操作实现,以下仅考虑前两种操作

为了方便,将优先级最高的节点作为根,显然根最后才会被删除

接下来,不断找到剩下的节点中(包括根)优先级最高的节点,将其到其所在树根的所有节点从下到上依次加入到序列的开头并删除,不难发现最终得到的序列即为燃烧的顺序

将每一次删除的链上的边称为实边,其余边称为虚边,实际上就构成了一个类似于LCT的结构

一次$v$的修改操作对该LCT的影响,简单分析后不难发现即为将$v$换为根

考虑节点$v$的答案,即分为两部分:

1.定义其中一条实链(一个Splay)的优先级为其中优先级最大的节点(链尾),所有实链中优先级比$v$所在实链小的长度(指节点个数)和

2.$v$所在实链中比$v$浅的点个数(包括$v$自身)

前者可以在LCT修改的过程中再维护一个树状数组(以优先级为下标,长度为权值),后者直接在LCT中查询该节点(将其Splay到根)即可,将两者求和即为答案

时间复杂度为$o(n\log n)$,可以通过

  1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 200005
4 struct Edge{
5 int nex,to;
6 }edge[N<<1];
7 int E,n,m,x,y,head[N],f[N<<1],st[N],fa[N],val[N],sz[N],rev[N],ch[N][2];
8 char s[11];
9 int lowbit(int k){
10 return (k&(-k));
11 }
12 void update(int k,int x){
13 while (k<=n+m){
14 f[k]+=x;
15 k+=lowbit(k);
16 }
17 }
18 int query(int k){
19 int ans=0;
20 while (k){
21 ans+=f[k];
22 k-=lowbit(k);
23 }
24 return ans;
25 }
26 int which(int k){
27 return ch[fa[k]][1]==k;
28 }
29 int check(int k){//返回1当且仅当不是根节点
30 return ch[fa[k]][which(k)]==k;
31 }
32 void upd(int k){
33 rev[k]^=1;
34 swap(ch[k][0],ch[k][1]);
35 }
36 void up(int k){
37 sz[k]=sz[ch[k][0]]+sz[ch[k][1]]+1;
38 }
39 void down(int k){
40 if (ch[k][0])val[ch[k][0]]=val[k];
41 if (ch[k][1])val[ch[k][1]]=val[k];
42 if (rev[k]){
43 upd(ch[k][0]);
44 upd(ch[k][1]);
45 rev[k]=0;
46 }
47 }
48 void rotate(int k){
49 int f=fa[k],g=fa[f],p=which(k);
50 fa[k]=g;
51 if (check(f))ch[g][which(f)]=k;
52 fa[ch[k][p^1]]=f,ch[f][p]=ch[k][p^1];
53 fa[f]=k,ch[k][p^1]=f;
54 up(f),up(k);
55 }
56 void splay(int k){
57 for(int i=k;;i=fa[i]){
58 st[++st[0]]=i;
59 if (!check(i))break;
60 }
61 while (st[0])down(st[st[0]--]);
62 for(int i=fa[k];check(k);i=fa[k]){
63 if (check(i)){
64 if (which(k)==which(i))rotate(i);
65 else rotate(k);
66 }
67 rotate(k);
68 }
69 }
70 void access(int k){
71 int lst=0;
72 while (k){
73 splay(k);
74 update(val[k],sz[ch[k][1]]-sz[k]);
75 ch[k][1]=lst,up(k);
76 lst=k,k=fa[k];
77 }
78 }
79 void make_root(int k){
80 access(k);
81 splay(k);
82 upd(k);
83 }
84 void add(int x,int y){
85 edge[E].nex=head[x];
86 edge[E].to=y;
87 head[x]=E++;
88 }
89 void dfs(int k,int f){
90 fa[k]=f,val[k]=k;
91 for(int i=head[k];i!=-1;i=edge[i].nex)
92 if (edge[i].to!=f){
93 dfs(edge[i].to,k);
94 val[k]=max(val[k],val[edge[i].to]);
95 }
96 update(val[k],1);
97 if (val[k]==k){
98 sz[k]=1;
99 return;
100 }
101 for(int i=head[k];i!=-1;i=edge[i].nex)
102 if ((edge[i].to!=f)&&(val[k]==val[edge[i].to])){
103 sz[k]=sz[edge[i].to]+1;
104 ch[k][1]=edge[i].to;
105 return;
106 }
107 }
108 void Update(int k){
109 make_root(k);
110 val[k]=++val[0];
111 update(val[k],sz[k]);
112 }
113 int Query(int k){
114 splay(k);
115 return query(val[k])-sz[ch[k][0]];
116 }
117 int main(){
118 scanf("%d%d",&n,&m);
119 memset(head,-1,sizeof(head));
120 for(int i=1;i<n;i++){
121 scanf("%d%d",&x,&y);
122 add(x,y),add(y,x);
123 }
124 dfs(n,0);
125 val[0]=n;
126 for(int i=1;i<=m;i++){
127 scanf("%s%d",s,&x);
128 if (s[0]=='u')Update(x);
129 if (s[0]=='w')printf("%d\n",Query(x));
130 if (s[0]=='c'){
131 scanf("%d",&y);
132 if (Query(x)<Query(y))printf("%d\n",x);
133 else printf("%d\n",y);
134 }
135 }
136 return 0;
137 }

[cf1137F]Matches Are Not a Child's Pla的更多相关文章

  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. [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. 数据库MySQL主从-GTID

    1.第一步在主服务器上/etc/my.cnf/下添加 log-bin=log-bin server-id=1 gtid_mode=ON enforce_gtid_consistency 2.第二步:重 ...

  2. 实战经验分享:使用 PyO3 来构建你的 Python 模块

    PyO3 主要用于创建原生 Python 的扩展模块.PyO3 还支持从 Rust 二进制文件运行 Python 代码并与之交互,可以实现 rust 与 Python 代码共存.在一些对性能要求较高的 ...

  3. CF536D Tavas in Kansas(博弈论+dp)

    貌似洛谷的题面是没有翻译的 QWQ 大致题面是这个样子,但是可能根据题目本身有不同的地方 完全懵逼的一个题(果然博弈论就是不一样) 首先,我们考虑把题目转化成一个可做的模型. 我们分别从\(s\)和\ ...

  4. ShardingSphere学习

    1 基本概念 1.1 ShardingSphere概述 官网:https://shardingsphere.apache.org/index_zh.html 1.2 分库分表概述 分库分表是为了解决由 ...

  5. 【数据结构与算法Python版学习笔记】树——树的遍历 Tree Traversals

    遍历方式 前序遍历 在前序遍历中,先访问根节点,然后递归地前序遍历左子树,最后递归地前序遍历右子树. 中序遍历 在中序遍历中,先递归地中序遍历左子树,然后访问根节点,最后递归地中序遍历右子树. 后序遍 ...

  6. TreeSet和TreeMap中“相等”元素可能并不相等

    TreeSet和TreeMap元素之间比较大小是借助Comparator对象的compare方法. 但有些时候,即便compare()返回0也不意味着这两个元素直观上相同. 比如元素是二元组[a,b] ...

  7. UltraSoft - Alpha - Scrum Meeting 1

    Date: Apr 06th, 2020. 会议内容为讨论功能规格书和技术规格书的撰写. Scrum 情况汇报 进度情况 组员 负责 昨日进度 后两日任务 CookieLau PM.后端 进行Djan ...

  8. 大牛针对零基础入门c语言详解指针(超详细)

    C语言指针说难不难但是说容易又是最容易出错的地方,因此不管是你要做什么只要用到C指针你就跳不过,今天咱们就以 十九个例子来给大家简单的分析一下指针的应用,最后会有C语言视频资料提供给大家更加深入的参考 ...

  9. 如何用PADS进行PCB设计?这6步就够了

    在使用PADS进行PCB设计的过程中,需要对印制板的设计流程以及相关的注意事项进行重点关注,这样才能更好的为工作组中的设计人员提供系统的设计规范,同时也方便设计人员之间进行相互的交流和检查. 02 设 ...

  10. 确定字符互异 牛客网 程序员面试金典 C++ Python

    确定字符互异 牛客网 程序员面试金典 C++ Python 题目描述 请实现一个算法,确定一个字符串的所有字符是否全都不同.这里我们要求不允许使用额外的存储结构. 给定一个string iniStri ...