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操作的可行性

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. #include<cmath>
  6. using namespace std;
  7. int size[],ch[][],rev[],pre[],isrt[],n,m,k[];
  8. void pushup(int o)
  9. {
  10. if (!o) return;
  11. size[o]=size[ch[o][]]+size[ch[o][]]+;
  12. }
  13. void pushdown(int o)
  14. {
  15. if (!o) return;
  16. if (rev[o])
  17. {
  18. int ls=ch[o][],rs=ch[o][];
  19. rev[ls]^=;
  20. swap(ch[ls][],ch[ls][]);
  21. rev[rs]^=;
  22. swap(ch[rs][],ch[rs][]);
  23. rev[o]=;
  24. }
  25. }
  26. void push(int o)
  27. {
  28. if (isrt[o]==) push(pre[o]);
  29. pushdown(o);
  30. }
  31. void rotate(int o,bool kind)
  32. {
  33. int p=pre[o];
  34. ch[p][!kind]=ch[o][kind];pre[ch[o][kind]]=p;
  35. if (isrt[p]) isrt[p]=,isrt[o]=;
  36. else ch[pre[p]][ch[pre[p]][]==p]=o;
  37. pre[o]=pre[p];
  38. ch[o][kind]=p;pre[p]=o;
  39. pushup(p);pushup(o);
  40. }
  41. void splay(int o)
  42. {
  43. push(o);
  44. while (isrt[o]==)
  45. {
  46. if (isrt[pre[o]])
  47. rotate(o,ch[pre[o]][]==o);
  48. else
  49. {
  50. int p=pre[o],kind=ch[pre[p]][]==p;
  51. if (ch[p][kind]==o)
  52. rotate(o,!kind),rotate(o,kind);
  53. else rotate(p,kind),rotate(o,kind);
  54. }
  55. }
  56. }
  57. void access(int o)
  58. {
  59. int y=;
  60. while (o)
  61. {
  62. splay(o);
  63. isrt[ch[o][]]=;
  64. isrt[ch[o][]=y]=;
  65. pushup(o);
  66. y=o;o=pre[o];
  67. }
  68. }
  69. void makeroot(int o)
  70. {
  71. access(o);
  72. splay(o);
  73. rev[o]^=;
  74. swap(ch[o][],ch[o][]);
  75. }
  76. void link(int x,int y)
  77. {
  78. makeroot(x);
  79. pre[x]=y;
  80. }
  81. void cut(int x,int y)
  82. {
  83. makeroot(x);
  84. access(y);splay(y);
  85. ch[y][]=;pre[x]=;
  86. isrt[x]=;
  87. pushup(y);
  88. }
  89. int main()
  90. {int i,c,x,y,st,ed;
  91. cin>>n;
  92. for (i=;i<=n+;i++)
  93. isrt[i]=,size[i]=;
  94. for (i=;i<=n;i++)
  95. {
  96. scanf("%d",&k[i]);
  97. if (i+k[i]>n) link(i,n+);
  98. else link(i,i+k[i]);
  99. }
  100. cin>>m;
  101. for (i=;i<=m;i++)
  102. {
  103. scanf("%d",&c);
  104. if (c==)
  105. {
  106. scanf("%d",&x);x++;
  107. makeroot(n+);
  108. access(x);
  109. splay(x);
  110. printf("%d\n",size[x]-);
  111. }
  112. else
  113. {
  114. scanf("%d%d",&x,&y);x++;
  115. if (k[x]+x>n) st=n+;
  116. else st=k[x]+x;
  117. if (y+x>n) ed=n+;
  118. else ed=y+x;
  119. k[x]=y;
  120. if (st!=ed)
  121. {
  122. cut(x,st);
  123. link(x,ed);
  124. }
  125. }
  126. }
  127. }

LCT

还有分块的做法

把n个点分成$sqrt n$块

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

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

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

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

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

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. #include<cmath>
  6. using namespace std;
  7. int n,k[],lim,s[],f[],m;
  8. int main()
  9. {int i,j,opt,x,now,cnt,y;
  10. cin>>n;
  11. for (i=;i<=n;i++)
  12. {
  13. scanf("%d",&k[i]);
  14. }
  15. lim=sqrt(n);
  16. for (i=;i<=n;i+=lim)
  17. {
  18. for (j=min(n,i+lim-);j>=i;j--)
  19. {
  20. if (k[j]+j>min(n,i+lim-)) s[j]=,f[j]=k[j]+j;
  21. else s[j]=s[j+k[j]]+,f[j]=f[k[j]+j];
  22. }
  23. }
  24. cin>>m;
  25. for (i=;i<=m;i++)
  26. {
  27. scanf("%d%d",&opt,&x);x++;
  28. if (opt==)
  29. {
  30. cnt=;
  31. while (x<=n)
  32. {
  33. cnt+=s[x];
  34. x=f[x];
  35. }
  36. printf("%d\n",cnt);
  37. }
  38. else
  39. {
  40. scanf("%d",&y);
  41. k[x]=y;
  42. if (x%lim==) now=x-lim+;
  43. else now=x-x%lim+;
  44. for (j=min(n,now+lim-);j>=now;j--)
  45. {
  46. if (k[j]+j>min(n,now+lim-)) s[j]=,f[j]=k[j]+j;
  47. else s[j]=s[j+k[j]]+,f[j]=f[k[j]+j];
  48. }
  49. }
  50. }
  51. }

分块

[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. 网络1711c语言第0次作业总结

    作业地址:https://edu.cnblogs.com/campus/jmu/JMUC--NE17111712/homework/861 总结 1.评分标准 以下要求中除了未交和抄袭0分,其他项最多 ...

  2. react基础篇入门组件

    讲述一下React: 1.声明式设计-React采用声明范式,可以轻松描述应用 2.高效-React通过DOM模型,最大限度的减少dom的交互 3.灵活-React可以与已知的库或框架很好的配合 4. ...

  3. python之路--day6--字符编码

    一.知识储备 cpu--控制和运算 内存--暂时存储cpu需要的数据 硬盘--永久保存数据2.文本编辑器的原理存储原理 1,启动文本编辑器 2,在编辑器上输入内容---此时输入内容还在内存上 3,保存 ...

  4. php函数var_dump() 、print_r()、echo()

    var_dump() 能打印出类型 print_r() 只能打出值 echo() 是正常输出... 需要精确调试的时候用 var_dump(); 一般查看的时候用 print_r() 另外 , ech ...

  5. MSIL实用指南-一维数组的操作

    本篇讲解怎么生成和操作一维数组.各种数组类型创建的步骤是一样的,但是加载和保存步骤有所不同. 一.创建数组所有类型的一维数组创建都是一样的,分三步.1.加载数组长度2.生成指令 Newarr < ...

  6. Linux的打印rpm包的详细信息的shell脚本

    #!/bin/bash # list a content summary of a number of RPM packages # USAGE: showrpm rpmfile1 rpmfile2 ...

  7. margin-top塌陷

    margin-top 塌陷 在两个不浮动的盒子嵌套时候,内部的盒子设置的margin-top会加到外边的盒子上,导致内部的盒子margin-top设置失败,解决方法如下: 1.外部盒子设置一个边框: ...

  8. mysql中的视图、事务和索引

    视图: 对于一个sql查询,如果发生了修改,就需要修改sql语句. 我们可以通过定义视图来解决问题.改变需求之后就改变视图. 视图是对查询的封装 定义视图: create view 视图名称 as s ...

  9. python/匿名函数和内置函数

    1 匿名函数 匿名函数是lambda定义的没有名字的具有一些小功能的函数 具体形式是 lambda 参数列表:返回值表达式 lambda x: X**2 # 求平方操作 lambda x: x> ...

  10. 道可道,非常道——详解promise

    promise 出来已久,以前一直使用,没有仔细剖析原理,最近在复习es6的知识,写一下自己对于promise的理解. promise是es6的一种异步编程解决方案,避免频繁的回调函数,增强代码的可阅 ...