P3203 [HNOI2010]弹飞绵羊

题目描述

某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏。游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹ki步,达到第i+ki个装置,若不存在第i+ki个装置,则绵羊被弹飞。绵羊想知道当它从第i个装置起步时,被弹几次后会被弹飞。为了使得游戏更有趣,Lostmonkey可以修改某个弹力装置的弹力系数,任何时候弹力系数均为正整数。

输入输出格式

输入格式:

第一行包含一个整数n,表示地上有n个装置,装置的编号从0到n-1。

接下来一行有n个正整数,依次为那n个装置的初始弹力系数。

第三行有一个正整数m,

接下来m行每行至少有两个数i、j,若i=1,你要输出从j出发被弹几次后被弹飞,若i=2则还会再输入一个正整数k,表示第j个弹力装置的系数被修改成k。

输出格式:

对于每个i=1的情况,你都要输出一个需要的步数,占一行。

说明

对于20%的数据n,m<=10000,对于100%的数据n<=200000,m<=100000


抽象一下问题,将弹飞的连到虚点\(n+1\)上,则图是一颗树,我们需要一个能修改边的,查询深度的连喵树。

我们发现其实不需要换根操作(然而本菜鸡最开始还打了)

\(link\)时提一个连一个虚边就行了

\(cat\)的时候把浅的\(access\)上去以后把深的\(splay\)一下然后直接断虚边

\(query\)时\(access\)一下,\(splay\)一下,就是左儿子大小。

事实上可以更简单


Code:

#include <cstdio>
#define ls ch[now][0]
#define rs ch[now][1]
#define fa par[now]
int min(int x,int y){return x<y?x:y;}
const int N=2e5+10;
int ch[N][2],siz[N],par[N],n,m,tmp,to[N];
bool isroot(int now)
{
return ch[fa][0]==now||ch[fa][1]==now;
}
int identity(int now)
{
return ch[fa][1]==now;
}
void updata(int now)
{
siz[now]=siz[ls]+siz[rs]+1;
}
void connect(int f,int now,int typ)
{
fa=f;ch[f][typ]=now;
}
void Rotote(int now)
{
int p=fa,typ=identity(now);
connect(p,ch[now][typ^1],typ);
if(isroot(p)) connect(par[p],now,identity(p));
else fa=par[p];
connect(now,p,typ^1);
updata(p),updata(now);
}
void splay(int now)
{
for(;isroot(now);Rotote(now))
if(isroot(fa))
Rotote(identity(now)^identity(fa)?now:fa);
}
void access(int now)
{
for(int las=0;now;las=now,now=fa)
splay(now),rs=las,updata(now);
}
void link(int u,int v)
{
access(v);
splay(u);
par[u]=v;
}
void cat(int u,int v)
{
access(v);
splay(u);
par[u]=0;
}
int query(int now)
{
access(now);
splay(now);
return siz[ls];
}
int main()
{
scanf("%d",&n);
for(int k,i=1;i<=n;i++)
{
scanf("%d",&k);
par[i]=min(i+k,n+1);
to[i]=par[i];
}
scanf("%d",&m);
for(int op,u,k,i=1;i<=m;i++)
{
scanf("%d%d",&op,&u);++u;
if(op==1) printf("%d\n",query(u));
else
{
scanf("%d",&k);
cat(u,to[u]);
to[u]=min(u+k,n+1);
link(u,to[u]);
}
}
return 0;
}

2018.8.11

洛谷 P3203 [HNOI2010]弹飞绵羊 解题报告的更多相关文章

  1. 洛谷P3203 [HNOI2010] 弹飞绵羊 [LCT]

    题目传送门 弹飞绵羊 题目描述 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置, ...

  2. 洛谷P3203 [HNOI2010]弹飞绵羊(LCT,Splay)

    洛谷题目传送门 关于LCT的问题详见我的LCT总结 思路分析 首先分析一下题意.对于每个弹力装置,有且仅有一个位置可以弹到.把这样的一种关系可以视作边. 然后,每个装置一定会往后弹,这不就代表不存在环 ...

  3. Bzoj2002/洛谷P3203 [HNOI2010]弹飞绵羊(分块)

    题面 Bzoj 洛谷 题解 大力分块,分块大小\(\sqrt n\),对于每一个元素记一下跳多少次能跳到下一个块,以及跳到下一个块的哪个位置,修改的时候时候只需要更新元素所在的那一块即可,然后询问也是 ...

  4. [洛谷P3203][HNOI2010]弹飞绵羊

    题目大意:有$n$个节点,第$i$个节点有一个弹力系数$k_i$,当到达第$i$个点时,会弹到第$i+k_i$个节点,若没有这个节点($i+k_i>n$)就会被弹飞.有两个操作: $x:$询问从 ...

  5. 洛谷 P3203 [HNOI2010]弹飞绵羊 || bzoj2002

    看来这个lct板子的确没什么问题 好像还可以分块做 #include<cstdio> #include<algorithm> using namespace std; type ...

  6. 洛谷 P3203 [HNOI2010]弹飞绵羊 分块

    我们只需将序列分成 n\sqrt{n}n​ 块,对于每一个点维护一个 val[i]val[i]val[i],to[i]to[i]to[i],分别代表该点跳到下一个块所需要的代价以及会跳到的节点编号.在 ...

  7. 洛谷 P3203 [HNOI2010]弹飞绵羊

    题意简述 有n个点,第i个点有一个ki,表示到达i这个点后可以到i + ki这个点 支持修改ki和询问一点走几次能走出所有点两个操作 题解思路 分块, 对于每个点,维护它走到下一块所经过的点数,它走到 ...

  8. 「洛谷P3202」[HNOI2010]弹飞绵羊 解题报告

    P3203 [HNOI2010]弹飞绵羊 题目描述 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始,Lostmonkey在地上沿着一 ...

  9. [Luogu P3203] [HNOI2010]弹飞绵羊 (LCT维护链的长度)

    题面 传送门:洛谷 Solution 这题其实是有类似模型的. 我们先考虑不修改怎么写.考虑这样做:每个点向它跳到的点连一条边,最后肯定会连成一颗以n+1为根的树(我们拿n+1代表被弹出去了).题目所 ...

随机推荐

  1. JavaSE 第二次学习随笔(四)

    ---------------------------------------------------------------------------------------------------- ...

  2. scala成长之路(3)隐式转换

    不废话,先上例子:定义一个参数类型为String的函数: scala> def sayHello(name:String) = println("hello " + name ...

  3. tomcat+nginx+keepalived的配置

    tomcat+nginx+keepalived的配置 1.在官网上下载Tomcat 2.将压缩包解压,并且移动到/opt/data/的目录下. .tar.gz /opt/data/ 3.进入到Tomc ...

  4. mysql 时间相关sql , 按天、月、季度、年等条件进行查询

    #今天 select * from or_order_task where to_days(created_date)=to_days(now()); #近七天 select * day )<= ...

  5. go学习笔记-类型转换(Type Conversion)

    类型转换(Type Conversion) 类型转换用于将一种数据类型的变量转换为另外一种类型的变,基本格式 type_name(expression) type_name 为类型,expressio ...

  6. Verilog学习笔记基本语法篇(七)········ 生成块

    生成块可以动态的生成Verilog代码.可以用于对矢量中的多个位进行重复操作.多个模块的实例引用的重复操作.根据参数确定程序中是否包含某段代码.生成语句可以控制变量的声明.任务和函数的调用.还能对实例 ...

  7. 10+ Best Responsive HTML5 AngularJS Templates

    http://www.responsivemiracle.com/collective/best-responsive-html5-angularjs-templates/

  8. 13 IO多路复用 (未完成)

    IO多路复用 6.select版-TCP服务器:最多1024 import select import socket import sys server = socket.socket(socket. ...

  9. 配置ORACLE的PRO*C环境

    1.访问数据库的方法    在ORACLE数据库管理和系统中,有三种访问数据库的方法:    ⑴.用SQL*Plus, 它有SQL命令以交互的应用程序访问数据库:    ⑵.用第四代语言应用开发工具开 ...

  10. 触发显示和隐藏 div

    <script> window.onload = function(){ var oDiv1 = document.getElementById("div1"); va ...