题目链接:

[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. VBA数组(十四)

    我们都知道,一个变量是一个存储值的容器. 有时,开发人员希望一次可以在一个变量中保存多个值. 当一系列值存储在单个变量中时,则称为数组变量. 数组声明 数组声明的方式与声明变量相同,只是数组变量的声明 ...

  2. JS中浏览器的数据存储机制

    一.JS中的三种数据存储方式 cookie.sessionStorage.localStorage 二.cookie 1.cookie的定义: cookie是存储在浏览器上的一小段数据,用来记录某些当 ...

  3. 部署Java项目到阿里云服务器(Ubuntu16.04 64位)

    生成Jar包 1.进入到项目所在的路径下,打开cmd命令控制台,使用如下命令打包项目. mvn package --前提将项目中使用的maven配置到系统的环境变量中 2.打包完成的jar包在项目目录 ...

  4. 【SpringMVC】统一异常处理

    一.需求 二.统一异常处理解决方案 2.1 定义异常 2.2 异常处理 2.3 配置统一异常处理器 2.4 异常处理逻辑 一.需求 一般项目中都需要作异常处理,基于系统架构的设计考虑,使用统一的异常处 ...

  5. CEIWEI CommMonitor 串口监控精灵v11.0 串口过滤 串口监控

    CEIWEI CommMonitor   串行端口监控精灵是用于 RS232 / RS422 / RS485 端口监控的专业 强大的系统实用程序软件.CEIWEI  CommMonitor 监控显示, ...

  6. FAILED: SemanticException Unable to determine if hdfs://tmaster:8020/user/root/words.db/test_t2 is encrypted

    使用hive时,建立数据库,建表,写数据: 读数据:select *  from test_t2; 报错SemanticException 原因:建表时使用了其他路径,或者在另一个路径的数据库(建立数 ...

  7. 使用aop注解实现表单防重复提交功能

    原文:https://www.cnblogs.com/manliu/articles/5983888.html 1.这里采用的方法是:使用get请求进入表单页面时,后台会生成一个tokrn_flag分 ...

  8. LoggerFactory is not a Logback LoggerContext but Logback is on the classpath. Either remove Logback or the competing implementation

    2019-06-26 22:19:57.408642475 java.lang.IllegalArgumentException: LoggerFactory is not a Logback Log ...

  9. 使用Ultra Librarian工具生成Altium封装和原理图符号的方法

    最近在项目中用到了TI的单通道SPDT 模拟开关TS5A3160芯片,Altium官方的库中没有该元件的封装库,所以需要自己画.Ti在官网的产品介绍中提供了生成原理图符号和 PCB 布局封装的方法. ...

  10. eclipse cdt 代码对齐

    ctrl + shift + F 快速对齐 平时对小节太不重视了 .