题目链接:

[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. element-ui default-checked-keys 会把节点下所有子节点全部勾选解决方法

    <el-tree class="filter-tree" :data="permissionData" :props="props" ...

  2. vue使用阿里矢量图标

    官方注册注册 1.加入购物车 在阿里矢量图标库将想要的图标加入购物车,然后在购物车中将图标添加到项目:     2.下载 到我的项目中,将图标下载到本地     3.解压引入 在vue项目的asset ...

  3. C#-NPOI操作EXCEL

    1.获取NUGET NPOI包. 2.引用命名空间 using NPOI.SS.UserModel;using NPOI.XSSF.UserModel;using NPOI.HSSF.UserMode ...

  4. zabbix server for Centos 6.3

    1.安装LNMP 参照http://lnmp.org/install.html 2.安装zabbix service 2.1下载zabbix,并解压 wget http://nchc.dl.sourc ...

  5. 前端BOM对象

    location.href 查看当前的url location.href http://www.baidu.com 跳转URL location.reload 重载当前页面 windows.alert ...

  6. 【OF框架】框架规范介绍

    一.目录规范 二.命名规范 三.其它规范

  7. 使用LPCXpresso开发板调试外部的电路板

    MCUXpresso IDE开发环境有一个主要的功能:支持LPC-Link2仿真调试器.通过这种方式,对于基于ARM的电路板,我可以使用这个功能强大的仿真调试器来调试.在NXP的众多LPCXpress ...

  8. Aure Event Hubs小白完全入门指南

    refer to https://www.cnblogs.com/mysunnytime/p/11634815.html?from=groupmessage&isappinstalled=0 ...

  9. 如何在linux系统下查看日志

    在linux系统下, 首先在idea中使用clean---->install----->package将这个项目进行打包,打包的方式 , 根据你在项目中的pom文件,最上面,可以查看到 这 ...

  10. 2018 南京网络预赛Sum ——莫比乌斯反演

    题意 设 $f(n)$ 为 $n=ab$ 的方案数,其中 $a,b$ 为无平方因子数.求 $\displaystyle  \sum_{i=1}^nf(i)$,$n \leq 2e7$. 分析 显然,可 ...