\[\texttt{Description}
\]

有 \(n\) 个弹力装置排成一排,第 \(i\) 个弹力装置的弹力系数是 \(k_i\) ,绵羊到第 \(i\) 个装置时,会被弹到第 \(i+k_i\) 个弹力装置,若第 \(i+k_i\) 个装置不存在,则绵羊被弹飞。

你要维护这 \(n\) 个弹力装置,支持 \(2\) 种操作:

  • 1 x 询问绵羊初始在第 \(x\) 个弹力装置时,被弹几次后被弹飞。
  • 2 x y 将 \(k_x\) 改成 \(y\) 。

\[\texttt{Solution}
\]

  • 我们把弹力装置抽象成一个点,弹力装置的这种位移操作抽象成一条边,即有 \(n\) 个点,第 \(i\) 个点向第 \(i+k_i\) 个点连一条边, 考虑到绵羊被弹飞的情况,我们新建一个虚拟节点 \(n+1\) ,若绵羊被第 \(i\) 个弹力装置弹飞(即 \(i+k_i>n\)),我们就使第 \(i\) 个点向第 \(n+1\) 点连一条边。

  • 考虑到每个节点都向后连边,我们建出来的图定是一个森林。

  • 对于查询操作,就是问第 \(x\) 个节点与第 \(n+1\) 个节点之间有几条边。

  • 对于修改操作,就是删去 \(x\) 原来向后连的边,再使得 \(x\) 向后新连一条边。

  • 发现需要动态维护森林,于是我们就可以用动态维护森林的利器:\(\mathsf{LCT}\) 。

  • 对于查询操作,我们依次调用 Make_root(x)access(n + 1)splay(n + 1),就把 \(x\) 到 \(n+1\) 的路径分出来了,若在辅助树上维护个 \(size_i\)(子树大小),此时答案即为 \(size_{n+1}-1\) (边数 \(=\) 点数 \(-\) \(1\))。

  • 对于修改操作,我们调用 Cut(x, x + k[x] > n ? n + 1 : x + k[x]) ,表示把 \(x\) 原来连出去的边删掉,再调用 k[x] = y 修改 \(k_x\) 的值,再调用 Link(x, x + k[x] > n ? n + 1 : x + k[x]),表示将 \(x\) 新连出去一条边。

\[\texttt{Code}
\]

  1. #include<cstdio>
  2. #include<algorithm>
  3. #define RI register int
  4. using namespace std;
  5. inline int read()
  6. {
  7. int x=0,f=1;char s=getchar();
  8. while(s<'0'||s>'9'){if(s=='-')f=-f;s=getchar();}
  9. while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
  10. return x*f;
  11. }
  12. const int N=1001000;
  13. int n,m;
  14. int fa[N],ch[N][2],k[N],size[N]; bool rev[N];
  15. int len,que[N];
  16. #define lc(x) ch[x][0]
  17. #define rc(x) ch[x][1]
  18. void upd(int x)
  19. {
  20. size[x]=size[lc(x)]+size[rc(x)]+1;
  21. }
  22. void spread(int x)
  23. {
  24. if(rev[x]==true)
  25. {
  26. std::swap(lc(x),rc(x));
  27. rev[lc(x)]^=1;rev[rc(x)]^=1;
  28. rev[x]=false;
  29. }
  30. }
  31. int get(int x)
  32. {
  33. return rc(fa[x])==x;
  34. }
  35. int Is_root(int x)
  36. {
  37. return lc(fa[x])!=x&&rc(fa[x])!=x;
  38. }
  39. void rotate(int x)
  40. {
  41. int y=fa[x],z=fa[y],chk=get(x);
  42. if(!Is_root(y))ch[z][ch[z][1]==y]=x;
  43. ch[y][chk]=ch[x][chk^1];fa[ch[x][chk^1]]=y;
  44. ch[x][chk^1]=y,fa[y]=x,fa[x]=z;
  45. upd(y),upd(x);
  46. }
  47. void splay(int x)
  48. {
  49. que[len=1]=x;
  50. for(RI p=x;!Is_root(p);p=fa[p])que[++len]=fa[p];
  51. for(RI i=len;i>=1;i--)spread(que[i]);
  52. for(;!Is_root(x);rotate(x))
  53. if(!Is_root(fa[x]))rotate(get(x)==get(fa[x])?fa[x]:x);
  54. }
  55. void access(int x)
  56. {
  57. for(RI y=0;x;y=x,x=fa[x])
  58. {
  59. splay(x);
  60. rc(x)=y,fa[y]=x;
  61. upd(x);
  62. }
  63. }
  64. int Find_root(int x)
  65. {
  66. access(x);
  67. splay(x);
  68. while(spread(x),lc(x))
  69. x=lc(x);
  70. splay(x);
  71. return x;
  72. }
  73. void Make_root(int x)
  74. {
  75. access(x);
  76. splay(x);
  77. rev[x]^=1;
  78. }
  79. void Link(int x,int y)
  80. {
  81. if(Find_root(x)==Find_root(y))
  82. return;
  83. Make_root(x);
  84. fa[x]=y;
  85. }
  86. void Cut(int x,int y)
  87. {
  88. Make_root(x);
  89. access(y);
  90. splay(y);
  91. if(lc(y)!=x||lc(x)||rc(x))
  92. return;
  93. lc(y)=fa[x]=0;
  94. upd(y);
  95. }
  96. int ask(int x,int y)
  97. {
  98. Make_root(x);
  99. access(y);
  100. splay(y);
  101. return size[y];
  102. }
  103. int main()
  104. {
  105. n=read();
  106. for(RI i=1;i<=n;i++)
  107. k[i]=read();
  108. for(RI i=1;i<=n;i++)
  109. Link(i,i+k[i]>n?n+1:i+k[i]);
  110. m=read();
  111. while(m--)
  112. {
  113. int opt=read(),x=read()+1;
  114. switch(opt)
  115. {
  116. case 1:{
  117. printf("%d\n",ask(x,n+1)-1);
  118. break;
  119. }
  120. case 2:{
  121. Cut(x,x+k[x]>n?n+1:x+k[x]);
  122. k[x]=read();
  123. Link(x,x+k[x]>n?n+1:x+k[x]);
  124. break;
  125. }
  126. }
  127. }
  128. return 0;
  129. }

\[\texttt{Thanks} \ \texttt{for} \ \texttt{watching}
\]

题解【[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. Spring中Bean的实例化与DI的过程

    引言 前文我们介绍了关于如何学习Spring的源码以及解析了spring中加载配置文件注册Beandefinition的过程.今天我们继续学习DI的过程. 创建实例和DI过程 IOC和DI都是对spr ...

  2. POJ 3304 Segments(判断直线与线段是否相交)

    题目传送门:POJ 3304 Segments Description Given n segments in the two dimensional space, write a program, ...

  3. 【转】iOS 7免费设计资源汇总

    原文链接:http://mobile.51cto.com/hot-406317.htm#585532-tsina-1-28470-7e393678b940a4d55500bf3feae3d2e9 以下 ...

  4. 使用iview遇到问题记录总结

    1.iview设置日期不可用,设置开始开始时间早于结束时间 官网示例,设置今天之前不可选,但是不能识别thisdisabledDate (date) { return date && ...

  5. MapGIS注记文字无损转入ArcGIS软件

    在GIS软件中,注释是一种十分特殊的对象,虽然各类软件都支持注释,但它却不属于GIS的基本对象.因此通常的格式转换软件,都不对注释对象做特别的支持,我们最常见的Shape文件格式就只有点.线.面要素, ...

  6. Scala实践10

    1.模式匹配 模式匹配是一种根据模式检查值的机制.它是switch(Java中语句)的更强大版本,它同样可以用来代替一系列if / else语句. 句法 匹配表达式具有值,match关键字和至少一个c ...

  7. input 只允许输入小数

    oninput = "value=value.replace(/[^\d]/g,'')" 输入浮点数不好使 突发奇想自己写一个与众不同的... oninput="valu ...

  8. SpringMVC启动流程源码解密

    我们知道,SpringMVC最后是通过Tomcat来进行部署的.当在Servlet中进行进行应用部署时,主要步骤为(引用来自http://download.oracle.com/otn-pub/jcp ...

  9. 区间dp - 送外卖

    When we are focusing on solving problems, we usually prefer to stay in front of computers rather tha ...

  10. MySql数据主从同步配置

    由于需要配置MySQL的主从同步配置,现将配置过程记录下,已被以后不时之需 MySql数据主从同步   1.1. 同步介绍 Mysql的 主从同步 是一个异步的复制过程,从一个 Master复制到另一 ...