洛谷P3203 [HNOI2010]弹飞绵羊(LCT,Splay)
关于LCT的问题详见我的LCT总结
思路分析
首先分析一下题意。对于每个弹力装置,有且仅有一个位置可以弹到。把这样的一种关系可以视作边。
然后,每个装置一定会往后弹,这不就代表不存在环么?
于是,一个森林的模型被我们建出来了。
考虑到有修改弹力值的操作,也就是要断边和连边,于是用LCT维护。
思路一
每一个点向它弹到的位置连边。如果被弹飞了,那么这条边就不存在。
查询弹飞的步数,就是查询该点到其所属原树中根节点的路径的\(size\)。
注意此题的一些特性。我们并不需要查询或者更改指定路径\((x-y)\)的信息。
也就是说,我们根本不需要换根!
原来需要换根的\(split,link,cut\)操作,我们可以根据题目特性适当调整一下。
- 查询原本需要\(split\),我们直接\(access(x),splay(x)\),输出\(x\)的\(size\)。
- 连边原本需要\(link\),题目保证了是一棵树,我们直接改\(x\)的父亲,连轻边。
- 断边原本需要\(cut\),然而我们确定其父亲的位置,\(access(x),splay(x)\)后,\(x\)的父亲一定在\(x\)的左子树中(LCT总结中的性质1),直接双向断开连接。
然后我们发现,程序一下子少了一堆函数(\(pushdown,makeroot,findroot,split,link,cut\))
代码少,常数小,何乐而不为?
下面贴代码
#include<cstdio>
#include<cstdlib>
#define R register int
#define I inline void
#define G ch=getchar()
#define gc G;while(ch<'-')G
#define in(z) gc;z=ch&15;G;while(ch>'-')z*=10,z+=ch&15,G;
const int N=200009;
int f[N],c[N][2],s[N];
bool r[N];
inline bool nroot(R x){
return c[f[x]][0]==x||c[f[x]][1]==x;
}
I pushup(R x){
s[x]=s[c[x][0]]+s[c[x][1]]+1;
}
I rotate(R x){
R y=f[x],z=f[y],k=c[y][1]==x,w=c[x][!k];
if(nroot(y))c[z][c[z][1]==y]=x;c[x][!k]=y;c[y][k]=w;
if(w)f[w]=y;f[y]=x;f[x]=z;
pushup(y);
}
I splay(R x){
R y,z;
while(nroot(x)){
y=f[x];z=f[y];
if(nroot(y))
rotate((c[y][0]==x)^(c[z][0]==y)?x:y);
rotate(x);
}
pushup(x);
}
I access(R x){
for(R y=0;x;x=f[y=x])
splay(x),c[x][1]=y,pushup(x);
}//以上是轻量化的LCT板子
int main()
{
register char ch;
R n,m,j,k;
in(n);
for(j=1;j<=n;++j){
s[j]=1;
in(k);
if(j+k<=n)f[j]=j+k;//如果弹飞了就不连边
}
in(m);
while(m--){
gc;
if(ch&1){
in(j);++j;
access(j);splay(j);//直接查询
printf("%d\n",s[j]);
}
else{
in(j);in(k);++j;
access(j);splay(j);
c[j][0]=f[c[j][0]]=0;//直接断边
if(j+k<=n)f[j]=j+k;//直接连边
pushup(j);
}
}
return 0;
}
思路2
把弹飞这种情况也可以视作一个节点(编号可定为\(n+1\))
如果弹飞了就把\(x\)连到这个点上,于是这个点稳稳地坐住了树根的位置。
查询的时候得到的\(size\)减\(1\)即可。
其它同上。
其实个人认为这样不如上面。动态树本身就定义为维护森林,多了这一个点等于强行把它变成一棵树,可能有点多此一举。。。。。。
代码如下,只贴main函数,因为LCT板子是一样的。。。。。。
int main()
{
register char ch;
R rt,n,m,j,k;
in(n);rt=n+1;
for(j=1;j<=rt;++j)s[j]=1;
for(j=1;j<=n;++j){
in(k);
f[j]=j+k>n?rt:j+k;//与上面不同
}
in(m);
while(m--){
gc;
if(ch&1){
in(j);++j;
access(j);splay(j);
printf("%d\n",s[j]-1);
}
else{
in(j);in(k);++j;
access(j);splay(j);
c[j][0]=f[c[j][0]]=0;
f[j]=j+k>n?rt:j+k;
pushup(j);
}
}
return 0;
}
洛谷P3203 [HNOI2010]弹飞绵羊(LCT,Splay)的更多相关文章
- 洛谷P3203 [HNOI2010] 弹飞绵羊 [LCT]
题目传送门 弹飞绵羊 题目描述 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置, ...
- 洛谷 P3203 [HNOI2010]弹飞绵羊 解题报告
P3203 [HNOI2010]弹飞绵羊 题目描述 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始,Lostmonkey在地上沿着一 ...
- [洛谷P3203][HNOI2010]弹飞绵羊
题目大意:有$n$个节点,第$i$个节点有一个弹力系数$k_i$,当到达第$i$个点时,会弹到第$i+k_i$个节点,若没有这个节点($i+k_i>n$)就会被弹飞.有两个操作: $x:$询问从 ...
- Bzoj2002/洛谷P3203 [HNOI2010]弹飞绵羊(分块)
题面 Bzoj 洛谷 题解 大力分块,分块大小\(\sqrt n\),对于每一个元素记一下跳多少次能跳到下一个块,以及跳到下一个块的哪个位置,修改的时候时候只需要更新元素所在的那一块即可,然后询问也是 ...
- 洛谷 P3203 [HNOI2010]弹飞绵羊 || bzoj2002
看来这个lct板子的确没什么问题 好像还可以分块做 #include<cstdio> #include<algorithm> using namespace std; type ...
- 洛谷 P3203 [HNOI2010]弹飞绵羊 分块
我们只需将序列分成 n\sqrt{n}n 块,对于每一个点维护一个 val[i]val[i]val[i],to[i]to[i]to[i],分别代表该点跳到下一个块所需要的代价以及会跳到的节点编号.在 ...
- 洛谷 P3203 [HNOI2010]弹飞绵羊
题意简述 有n个点,第i个点有一个ki,表示到达i这个点后可以到i + ki这个点 支持修改ki和询问一点走几次能走出所有点两个操作 题解思路 分块, 对于每个点,维护它走到下一块所经过的点数,它走到 ...
- [Luogu P3203] [HNOI2010]弹飞绵羊 (LCT维护链的长度)
题面 传送门:洛谷 Solution 这题其实是有类似模型的. 我们先考虑不修改怎么写.考虑这样做:每个点向它跳到的点连一条边,最后肯定会连成一颗以n+1为根的树(我们拿n+1代表被弹出去了).题目所 ...
- P3203 [HNOI2010]弹飞绵羊(LCT)
弹飞绵羊 题目传送门 解题思路 LCT. 将每个节点的权值设为\(1\),连接\(i\)和\(i+ki\),被弹飞就连上\(n\),维护权值和\(sum[]\).从\(j\)弹飞需要的次数就是\(sp ...
随机推荐
- S5PV210时钟,看门狗定时器
晶振:时钟源(操作主要有两个,倍频,分频) A8的时钟源: 时钟域,每个时钟域(不同的最高频率和最低频率)管理着不同的电路模块: 不同的时钟域对应不同电路模块表 时钟电路:懂得看时钟电路(时钟源选择开 ...
- HashMap中的散列函数、冲突解决机制和rehash
一.概述 散列算法有两个主要的实现方式:开散列和闭散列,HashMap采用开散列实现. HashMap中,键值对(key-value)在内部是以Entry(HashMap中的静态内部类)实例的方式存储 ...
- Spring 依赖注入的理解
首先: 1.依赖注入就是一种在一个需要使用它的类中定义一个接口,该类中不管这个接口是怎么实现的,只是执行这个方法 2.依赖注入可以让该类实现通用 代码: 1.定义一个饮料接口 package cn.l ...
- Flask從入門到入土(三)——Web表單
Flask-WTF擴展可以把處理Web表單的過程變成一種愉悅的體驗.這個擴展對獨立的WTForms包進行了包裝,方便集成到Flask程序中. Flask-WTF及其依賴可使用pip安裝: pip in ...
- 算法提高 金属采集 树形DP
题目链接:金属采集 思路:d(i, j)表示在以i为根结点的子树中使用j个机器人的最小花费.设v为u的一个子节点,从节点i使用k个机器人收集以v为根结点的能量,状态转移方程为d(u, i) = min ...
- SpringBoot+gradle+idea实现热部署和热加载
前言 因为之前使用myeclipes的同学就知道,在使用myeclipes的时候,java文件或者jsp文件写完之后会被直接热加载到部署的容器中,从而在开发的时候,不同经常去重启项目,从而达到了增加开 ...
- 弄懂 JRE、JDK、JVM 之间的区别与联系
其实很多 Java 程序员在写了很多代码后,你问他 jre 和 jdk 之间有什么关系,jvm 又是什么东西,很多人不知所云.本篇不会讲述 jvm 底层是如何与不同的系统进行交互的,而主要理清楚三者之 ...
- 最简化搭建yum仓库
在使用rpm安装软件包时,时常会遇到一些软件依赖性问题,如果是简单的一两个依赖性还是可以手动解决.要是出现大量的依赖性问题的话会让增大工作量.yum是一个很好的前端程序,可解决软件包相关依赖性,可在多 ...
- hadoop/storm以及hive/hbase/pig区别整理
STORM与HADOOP的比较 对于一堆时刻在增长的数据,如果要统计,可以采取什么方法呢? 等数据增长到一定程度的时候,跑一个统计程序进行统计.适用于实时性要求不高的场景.如将数据导到HDFS,再运行 ...
- ajax的缺点
平时我们大多注意的都是ajax给我们所带来的好处诸如用户体验的提升.对ajax所带来的缺陷有所忽视. 下面所阐述的ajax的缺陷都是它先天所产生的. 1.ajax干掉了back按钮,即对浏览器后退机制 ...