洛谷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 ...
随机推荐
- Orleans之EventSourcing
Orleans之EventSourcing 这是Orleans系列文章中的一篇.首篇文章在此 引入: 如果没有意外,我再这篇文章中用ES代替EventSourcing,如果碰到"事件回溯&q ...
- 用Markdown写微信公众号文章
目前微信公众号的编辑器是不支持Markdown语法的,那怎么办呢? 有一款叫Markdown Here的插件可以解决这个问题(支持Chrome.Firefox.Safari). 官方网站:http:/ ...
- python学习:收集主机信息
#!/usr/bin/env python from subprocess import Popen, PIPE def getIfconfig(): p = Popen(['ifco ...
- ansible实践2-拷贝文件或目录
ansible testhost -m copy -a "src=/etc/ansible dest=/tmp/ansibletest owner=root group=root mo ...
- 实现dedecms全站动态浏览 并实现伪静态
dedecms默认是生成静态文件,如何实现织梦全站动态浏览呢? 织梦全站动态浏览方法 1. 修改首页为动态浏览 后台-生成-更新首页-勾选"仅动态浏览" 2. 修改栏目页为动态浏览 ...
- oracle 11.2.0.2以后对数据库用户名重命名
本文来自我的github pages博客http://galengao.github.io/ 即www.gaohuirong.cn [转自]http://www.xifenfei.com/2012/0 ...
- Struts2 基本的ResultType 【学习笔记】
在struts2-core.jar/struts-default.xml中,我们可以找到关于result-type的一些配置信息,从中可以看出struts2组件默认为我们提供了这 些result-ty ...
- C语言_简单的阶乘函数
include <stdio.h> long jc (int num); long jc2 (int num); int main() { long n; n = jc(); printf ...
- SSRF漏洞总结
SSRF漏洞:(服务端请求伪造)是一种由攻击者构造形成由服务端发起请求的一个安全漏洞.一般情况下,SSRF攻击的目标是从外网无法访问的内部系统.(正是因为它是由服务端发起的,所以它能够请求到与它相连而 ...
- windows NLB实现MSSQL读写分离--从数据库集群读负载均衡
主从模式,几乎大部分出名的数据库都支持的一种集群模式. 当Web站点的访问量上去之后,很多站点,选择读写分离,减轻主数据库的的压力.当然,一主多从也可以作用多个功能,比如备份.这里主要演示如何实现从数 ...