题目描述

某天,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。对于20%的数据n,m<=10000,对于100%的数据n<=200000,m<=100000

输出

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

样例输入

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

样例输出

2
3
 
当跳过n之后就被弹飞,那么可以建一个虚点n+1,将弹飞看作弹到n+1这个节点上。
i会被弹到i+ki号节点上,那么直接将i号节点和i+ki号节点连上就好了。
修改直接断开原来连的边,重新连接一条边,LCT维护就好了。
因为每个点只会连接一个比它编号大的点,所以最后形成了一棵树,每次询问直接查询j和n+1路径上的节点数-1即可。

#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<cstdio>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,m;
int x,y;
int opt;
int s[200020][2];
int f[200020];
int r[200020];
int st[200020];
int size[200020];
int dis[200020];
int 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(r[rt])
{
r[s[rt][0]]^=1;
r[s[rt][1]]^=1;
r[rt]^=1;
swap(s[rt][0],s[rt][1]);
}
}
int is_root(int rt)
{
return rt!=s[f[rt]][0]&&rt!=s[f[rt]][1];
}
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[fa][k]]=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]=x;
pushup(rt);
}
}
void reverse(int rt)
{
access(rt);
splay(rt);
r[rt]^=1;
}
int find(int rt)
{
access(rt);
splay(rt);
while(s[rt][0])
{
rt=s[rt][0];
}
return rt;
}
void link(int x,int y)
{
reverse(x);
f[x]=y;
}
void cut(int x,int y)
{
reverse(x);
access(y);
splay(y);
s[y][0]=f[x]=0;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n+1;i++)
{
size[i]=1;
}
for(int i=1;i<=n;i++)
{
scanf("%d",&x);
dis[i]=x;
if(i+x<=n)
{
link(i,i+x);
}
else
{
link(i,n+1);
}
}
scanf("%d",&m);
while(m--)
{
scanf("%d",&opt);
if(opt==1)
{
scanf("%d",&x);
x++;
reverse(x);
access(n+1);
splay(n+1);
printf("%d\n",size[n+1]-1);
}
else
{
scanf("%d%d",&x,&y);
x++;
if(x+dis[x]<=n)
{
cut(x,x+dis[x]);
}
else
{
cut(x,n+1);
}
dis[x]=y;
if(x+dis[x]<=n)
{
link(x,x+dis[x]);
}
else
{
link(x,n+1);
}
}
}
}

BZOJ2002[Hnoi2010]弹飞绵羊——LCT的更多相关文章

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

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

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

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

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

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

  4. BZOJ2002 [HNOI2010] 弹飞绵羊

    LCT access完了一定splay再用!!! 悲伤= = LCT裸题 把调出去设虚点n+1即可 //Love and Freedom. #include<cstdio> #includ ...

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

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

  6. 【BZOJ2002】弹飞绵羊(Link-Cut Tree)

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

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

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

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

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

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

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

随机推荐

  1. saltstack配置管理之states

    states是saltstack中的配置语言,我们安装一个包,管理一个配置文件,最后保证服务的正常运行,都需要我们编写一些states sls文件(描述状态的文件)去描述和实现我们的功能.sls文件都 ...

  2. android 工具大集合

    http://www.androiddevtools.cn/ http://www.sourcetreeapp.com/

  3. arm那些事

    ARM简介 ARM的商业模式: ARM只负责设计IC,并且出卖自己的设计IP(版权). ARM自己不生产芯片,而是把设计IP授权给其他半导体厂商来生产芯片. 严格地说,ARM并不是一家半导体厂商.   ...

  4. 走近SpringBoot

    (博客园不支持MarkDown编辑,看完整版请移步:https://www.zybuluo.com/Allen-llh/note/1199946) 1. (Building a RESTful Web ...

  5. Bootstrap动态轮播

    一.前台界面 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEn ...

  6. C#中,使用显式类型转换(int)和Math.Round方法,将浮点数转换为整数的区别

    主要区别就是,显式类型转换(int)是将浮点数的整数部分截取出来,然后转换为整数,所以相当于是向下取整.而Math.Round方法是对浮点数进行四舍五入后,转换为整数. 新建一个.NET Core控制 ...

  7. 3.《想成为黑客,不知道这些命令行可不行》(Learn Enough Command Line to Be Dangerous)——检查文件

    上面我们已经学过如何创建及操作文件,现在我们再来学习检查内容.当文件太长以至于屏幕一页显示不完时,这显得尤其重要.特殊情形下,如我们在第2.1章节开始部分中使用cat命令将内容展示到屏幕上,但这对于长 ...

  8. GATT服务搜索流程(二)

    关于bta_dm_cb.p_sec_cback,这里我们之前已经分析过,他就是bte_dm_evt ,最终调用的函数btif_dm_upstreams_evt : static void btif_d ...

  9. JavaScript 利用 async await 实现 sleep 效果

    const sleep = (timeountMS) => new Promise((resolve) => { setTimeout(resolve, timeountMS); }); ...

  10. 个人博客地址: furur.xyz

    趁着Hexo的热度,最近就买了域名,在GitHub Pages上搭了个人博客.也不是说博客园不好吧,毕竟在博客园三年多,也学到了不少东西,唯一要吐槽的,估计也就是后台管理不方便,markdown无即时 ...