题目链接:

[Codeforces1137F]Matches Are Not a Child's Play

题目大意:

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

例如对于上图中的树,它的删除序列为:$2\ 4\ 3\ 1\ 5$

现在给出一棵$n$个节点的树,有$m$次操作:

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

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

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

显然编号最大的点在序列的最后一位(设为$y$),我们以这个点为根,那么删除就是从下往上删除一段一段的链。

将连续删除的一段链看成是一条重链,整棵树就被分成了若干条重链。

可以发现每条重链的最低端的节点标号是这条重链上最大的。

因为如果要删除链底的那个点,那么说明当前能删除的点都比链底的点大,在删除链底之后一定会连续删除链上的所有点。

现在来考虑一次$up\ x$操作带来的影响:显然最后删除的一定是从$y$到$x$的链,而剩下的点在序列上的相对位置不变。

对于树来说就是将$x$到$y$变成一条重链并将$x$变为根节点。

我们用$LCT$来维护这些重链,对于每条重链按链上的编号最大值来编号,用树状数组来记录每个重链的大小。

$up$操作就相当于$LCT$中的$access$,在$access$时同步修改树状数组上记录的信息即可。

$when$操作就是查重链编号比自己所在重链的编号小的所有重链大小之和及自己所在重链下方的节点数。

$compare$操作就是两个$when$操作。

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<cstdio>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
int f[200010];
int s[200010][2];
int size[200010];
int st[200010];
int v[400010];
int tot;
int head[200010];
int nex[400010];
int to[400010];
char ch[10];
int n,m;
int x,y;
int cnt;
int rev[200010];
int val[200010];
void add_edge(int x,int y)
{
nex[++tot]=head[x];
head[x]=tot;
to[tot]=y;
}
void add(int x,int k)
{
for(int i=x;i<=n+m;i+=i&-i)
{
v[i]+=k;
}
}
int ask(int x)
{
int res=0;
for(int i=x;i;i-=i&-i)
{
res+=v[i];
}
return res;
}
void dfs(int x)
{
val[x]=x;
size[x]=1;
for(int i=head[x];i;i=nex[i])
{
if(to[i]!=f[x])
{
f[to[i]]=x;
dfs(to[i]);
if(val[to[i]]>val[x])
{
val[x]=val[to[i]];
s[x][1]=to[i];
size[x]=size[to[i]]+1;
}
}
}
add(val[x],1);
}
bool is_root(int rt)
{
return rt!=s[f[rt]][0]&&rt!=s[f[rt]][1];
}
bool get(int rt)
{
return rt==s[f[rt]][1];
}
void pushup(int rt)
{
size[rt]=size[s[rt][0]]+size[s[rt][1]]+1;
}
void pushdown(int rt)
{
if(rev[rt])
{
swap(s[rt][0],s[rt][1]);
rev[s[rt][0]]^=1;
rev[s[rt][1]]^=1;
rev[rt]=0;
}
if(s[rt][0])val[s[rt][0]]=val[rt];
if(s[rt][1])val[s[rt][1]]=val[rt];
}
void rotate(int rt)
{
int fa=f[rt];
int anc=f[fa];
int k=get(rt);
if(!is_root(fa))
{
s[anc][get(fa)]=rt;
}
s[fa][k]=s[rt][k^1];
f[s[rt][k^1]]=fa;
s[rt][k^1]=fa;
f[fa]=rt;
f[rt]=anc;
pushup(fa);
pushup(rt);
}
void splay(int rt)
{
int top=0;
st[++top]=rt;
for(int i=rt;!is_root(i);i=f[i])
{
st[++top]=f[i];
}
for(int i=top;i>=1;i--)
{
pushdown(st[i]);
}
for(int fa;!is_root(rt);rotate(rt))
{
if(!is_root(fa=f[rt]))
{
rotate(get(fa)==get(rt)?fa:rt);
}
}
}
void access(int rt)
{
for(int x=0;rt;x=rt,rt=f[rt])
{
splay(rt);
s[rt][1]=0;
pushup(rt);
add(val[rt],-size[rt]);
add(cnt,size[rt]);
s[rt][1]=x;
pushup(rt);
}
}
void reverse(int rt)
{
cnt++;
access(rt);
splay(rt);
rev[rt]^=1;
val[rt]=cnt;
}
int query(int rt)
{
splay(rt);
return ask(val[rt])-size[s[rt][0]];
}
int main()
{
scanf("%d%d",&n,&m);
cnt=n;
for(int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
add_edge(x,y);
add_edge(y,x);
}
dfs(n);
for(int i=1;i<=m;i++)
{
scanf("%s",ch);
if(ch[0]=='u')
{
scanf("%d",&x);
reverse(x);
}
else if(ch[0]=='w')
{
scanf("%d",&x);
printf("%d\n",query(x));
}
else
{
scanf("%d%d",&x,&y);
printf("%d\n",query(x)<query(y)?x:y);
}
}
}

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

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

  4. 【树链剖分 ODT】cf1137F. Matches Are Not a Child's Play

    孔爷的杂题系列:LCT清新题/ODT模板题 题目大意 定义一颗无根树的燃烧序列为:每次选取编号最小的叶子节点形成的序列. 要求支持操作:查询一个点$u$在燃烧序列中的排名:将一个点的编号变成最大 $n ...

  5. CF1137F Matches Are Not a Child's Play

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

  6. [cf1137F]Matches Are Not a Child's Pla

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

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

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

  8. Codeforces Round #250 (Div. 1) D. The Child and Sequence 线段树 区间取摸

    D. The Child and Sequence Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest ...

  9. Codeforces 438D The Child and Sequence - 线段树

    At the children's day, the child came to Picks's house, and messed his house up. Picks was angry at ...

随机推荐

  1. vue单页面应用加入百度统计

    版权声明:本文为CSDN博主「钟文辉」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明.原文链接:https://blog.csdn.net/qq_39753974/a ...

  2. Source Insight用法

    快捷键 Symbol: Browse Project Symbols-:F7, Alt+G Relation View Relationship->For Functions->Pefer ...

  3. jquery-weui滚动事件的注册与注销

    注册infinite(50)是自定义的,详细暂时没去了解,可以不写即代表默认值. // body是整一块代码的标签,也就是滚动的部分. $('body').infinite().on("in ...

  4. py-2 python介绍与安装

    一.python介绍 1.python背景 python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,Guido开始写能够解释Python语言语法的解释器.Py ...

  5. Linux之mysql的安装与,主从设置

    一,MYSQL(mariadb) MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可. 开发这个分支的原因之一是:甲骨文公司收购了MySQL后,有将MySQL ...

  6. 有关Error during sbt execution: No Scala version specified or detected的解决方案--SBT

    sbt 全称为 Simple Build Tool,是 Scala 项目中的标准构建工具,类似于 Java 下的 Maven/Groovy 中的 Gradle. 项目的构建 项目依赖自动化管理 提供统 ...

  7. PAT基础级-钻石段位样卷2-7-3 大笨钟 (10 分)

    微博上有个自称“大笨钟V”的家伙,每天敲钟催促码农们爱惜身体早点睡觉.不过由于笨钟自己作息也不是很规律,所以敲钟并不定时.一般敲钟的点数是根据敲钟时间而定的,如果正好在某个整点敲,那么“当”数就等于那 ...

  8. PAT_B1013

    这道题就是一道打印素数表的题目,本人使用的是筛选法,用bool数组记录是否为素数,每一次筛掉本轮数字的倍数,如果当前数字bool数组对应位置为false,则为素数. 这道题的坑是:你不知道最大第100 ...

  9. Thrift使用入门---RPC服务

    https://blog.csdn.net/zkp_java/article/details/81879577 RPC基本原理 大部分的RPC框架都遵循如下三个开发步骤: RPC通信过程如下图所示 通 ...

  10. Codeforces 348 D - Turtles Lindström–Gessel–Viennot lemma

    #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second ...