Description

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

Input

第一行包含一个整数n,表示地上有n个装置,装置的编号从0到n-1,接下来一行有n个正整数,依次为那n个装置的初始弹力系数。第三行有一个正整数m,接下来m行每行至少有两个数i、j,若i=1,你要输出从j出发被弹几次后被弹飞,若i=2则还会再输入一个正整数k,表示第j个弹力装置的系数被修改成k。对于20%的数据n,m<=10000,对于100%的数据n<=200000,m<=100000

Output

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

Sample Input

4
1 2 1 1
3
1 1
2 1 1
1 1

Sample Output

2
3

先建树,如果i+k大于n,就和n+1,建边表示弹出,否则和i+k建边

建树用LCT的link操作

修改就cut操作删掉旧边,加上新边

查询时,把n+1变为树根,把x到n+1都变为实根

查询路径上节点数-1输出

splay维护size,因为总是只有一颗完整的树,所以不需要判断cut和link操作的可行性

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int size[],ch[][],rev[],pre[],isrt[],n,m,k[];
void pushup(int o)
{
if (!o) return;
size[o]=size[ch[o][]]+size[ch[o][]]+;
}
void pushdown(int o)
{
if (!o) return;
if (rev[o])
{
int ls=ch[o][],rs=ch[o][];
rev[ls]^=;
swap(ch[ls][],ch[ls][]);
rev[rs]^=;
swap(ch[rs][],ch[rs][]);
rev[o]=;
}
}
void push(int o)
{
if (isrt[o]==) push(pre[o]);
pushdown(o);
}
void rotate(int o,bool kind)
{
int p=pre[o];
ch[p][!kind]=ch[o][kind];pre[ch[o][kind]]=p;
if (isrt[p]) isrt[p]=,isrt[o]=;
else ch[pre[p]][ch[pre[p]][]==p]=o;
pre[o]=pre[p];
ch[o][kind]=p;pre[p]=o;
pushup(p);pushup(o);
}
void splay(int o)
{
push(o);
while (isrt[o]==)
{
if (isrt[pre[o]])
rotate(o,ch[pre[o]][]==o);
else
{
int p=pre[o],kind=ch[pre[p]][]==p;
if (ch[p][kind]==o)
rotate(o,!kind),rotate(o,kind);
else rotate(p,kind),rotate(o,kind);
}
}
}
void access(int o)
{
int y=;
while (o)
{
splay(o);
isrt[ch[o][]]=;
isrt[ch[o][]=y]=;
pushup(o);
y=o;o=pre[o];
}
}
void makeroot(int o)
{
access(o);
splay(o);
rev[o]^=;
swap(ch[o][],ch[o][]);
}
void link(int x,int y)
{
makeroot(x);
pre[x]=y;
}
void cut(int x,int y)
{
makeroot(x);
access(y);splay(y);
ch[y][]=;pre[x]=;
isrt[x]=;
pushup(y);
}
int main()
{int i,c,x,y,st,ed;
cin>>n;
for (i=;i<=n+;i++)
isrt[i]=,size[i]=;
for (i=;i<=n;i++)
{
scanf("%d",&k[i]);
if (i+k[i]>n) link(i,n+);
else link(i,i+k[i]);
}
cin>>m;
for (i=;i<=m;i++)
{
scanf("%d",&c);
if (c==)
{
scanf("%d",&x);x++;
makeroot(n+);
access(x);
splay(x);
printf("%d\n",size[x]-);
}
else
{
scanf("%d%d",&x,&y);x++;
if (k[x]+x>n) st=n+;
else st=k[x]+x;
if (y+x>n) ed=n+;
else ed=y+x;
k[x]=y;
if (st!=ed)
{
cut(x,st);
link(x,ed);
}
}
}
}

LCT

还有分块的做法

把n个点分成$sqrt n$块

预处理出f[i],s[i]

f[i]表示i会跳到下一块的地方

s[i]表示i跳到f[i]所需要的步数

查询时直接往后跳,最多跳$sqrt n$块

修改时只修改那一块$sqrt n$个元素

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int n,k[],lim,s[],f[],m;
int main()
{int i,j,opt,x,now,cnt,y;
cin>>n;
for (i=;i<=n;i++)
{
scanf("%d",&k[i]);
}
lim=sqrt(n);
for (i=;i<=n;i+=lim)
{
for (j=min(n,i+lim-);j>=i;j--)
{
if (k[j]+j>min(n,i+lim-)) s[j]=,f[j]=k[j]+j;
else s[j]=s[j+k[j]]+,f[j]=f[k[j]+j];
}
}
cin>>m;
for (i=;i<=m;i++)
{
scanf("%d%d",&opt,&x);x++;
if (opt==)
{
cnt=;
while (x<=n)
{
cnt+=s[x];
x=f[x];
}
printf("%d\n",cnt);
}
else
{
scanf("%d",&y);
k[x]=y;
if (x%lim==) now=x-lim+;
else now=x-x%lim+;
for (j=min(n,now+lim-);j>=now;j--)
{
if (k[j]+j>min(n,now+lim-)) s[j]=,f[j]=k[j]+j;
else s[j]=s[j+k[j]]+,f[j]=f[k[j]+j];
}
}
}
}

分块

[HNOI2010]弹飞绵羊的更多相关文章

  1. P3203 [HNOI2010]弹飞绵羊(LCT)

    P3203 [HNOI2010]弹飞绵羊 LCT板子 用一个$p[i]$数组维护每个点指向的下个点. 每次修改时cut*1+link*1就解决了 被弹出界时新设一个点,权为0,作为终点表示出界点.其他 ...

  2. [HNOI2010] 弹飞绵羊 (分块)

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

  3. 洛谷 P3203 [HNOI2010]弹飞绵羊 解题报告

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

  4. [BZOJ 2002] [HNOI2010]弹飞绵羊(Link Cut Tree)

    [BZOJ 2002] [HNOI2010]弹飞绵羊(Link Cut Tree) 题面 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一 ...

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

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

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

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

  7. P3203 [HNOI2010]弹飞绵羊 —— 懒标记?分块?LCT?...FAQ orz

    好久没写博客了哈,今天来水一篇._(:з」∠)_ 题目 :弹飞绵羊(一道省选题) 题目描述 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏 ...

  8. P3203 [HNOI2010]弹飞绵羊 —— 懒标记?分块?

    好久没写博客了哈,今天来水一篇._(:з」∠)_ 题目 :弹飞绵羊(一道省选题) 题目描述 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏 ...

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

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

  10. P3203 [HNOI2010]弹飞绵羊(LCT)

    弹飞绵羊 题目传送门 解题思路 LCT. 将每个节点的权值设为\(1\),连接\(i\)和\(i+ki\),被弹飞就连上\(n\),维护权值和\(sum[]\).从\(j\)弹飞需要的次数就是\(sp ...

随机推荐

  1. JavaScript(第七天)【对象和数组】

    什么是对象,其实就是一种类型,即引用类型.而对象的值就是引用类型的实例.在ECMAScript中引用类型是一种数据结构,用于将数据和功能组织在一起.它也常被称做为类,但ECMAScript中却没有这种 ...

  2. 201621123050 《Java程序设计》第3周学习总结

    1. 本周学习总结 初学面向对象,会学习到很多碎片化的概念与知识.尝试学会使用思维导图将这些碎片化的概念.知识点组织起来.请使用工具画出本周学习到的知识点及知识点之间的联系.步骤如下: 1.1 写出你 ...

  3. DML数据操作语言之查询(一)

    1.select语句基础 基本语句格式:  select <列名>,.... from <表名>; select子句中列举出希望从表中查询出的列的名称,from子句则指定了选取 ...

  4. 第一次PTA作业

    题目6-1拆分实数整数及小数部分 1设计思路 (1) 第一步:阅读题目要求及所给部分. 第二步:根据题意补全相应函数. (2)流程图 无 2.实验代码 #include <stdio.h> ...

  5. AngularJS1.X学习笔记7-过滤器

    最近参加笔试被虐成狗了,感觉自己的算法太弱了.但是还是先花点事件将这个AngularJS学习完.今天学习filter 一.内置过滤器 (1)过滤单个数据值 <!DOCTYPE html> ...

  6. Python内置函数(33)——any

    英文文档: any(iterable) Return True if any element of the iterable is true. If the iterable is empty, re ...

  7. wordpress | WP Mail SMTP使用QQ邮箱发布失败的解决办法

    在使用contact form 7插件时遇到邮件发送失败的问题,经过检查发现是因为服务器不支持mail()函数,判断是否支持mail()函数可以参考http://www.diyzhan.com/201 ...

  8. python中的赋值与深浅拷贝

    Python当中对于拷贝,分为两种类型.一种是数字和字符串,另一种就是列表.元组.字典等其他类型了. 一.数字和字符串的拷贝 1.赋值 举个栗子: a1 = 123123 a2 = 123123 # ...

  9. SpringCloud的服务注册中心(三) - 进一步了解 Eureka

    一.服务治理参与者 服务注册中心: eureka-server 服务提供者:HELLO-SERVICE 服务消费者 :HELLO-CONSUMER 很多时候,客户端既是服务提供者又是服务消费者,-&g ...

  10. SpringBoot的重要特性

    一.Web特性 Spring Boot 提供了spring-boot-starter-web来为Web开发予以支持,spring-boot-starter-web为我们提供了嵌入的Tomcat以及Sp ...