BZOJ2002 [Hnoi2010]Bounce 弹飞绵羊


Solution

很早以前写的一道分块题,最近在搞LCT,又做了一遍.

1.LCT做法

看到这种动态修改,想下LCT怎么维护.

修改操作就是\(Cut(x,k[x])\)然后再\(Link(x,k[x]')\)

剩下的只有询问了.

我们如果把弹出设为一个新节点\(n+1\),那么显然就是直接:

\(makeroot(x)\),\(access(n+1)\),\(splay(n+1)\).

最后答案就是\(siz[n+1].\)

2.分块做法

我们如果把编号分块,那么显然每一次修改就维护一下弹出的到了哪个块,然后随便搞一下就可以了.

代码实现

LCT

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<string.h>
  4. #include<math.h>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<set>
  8. #include<map>
  9. #include<iostream>
  10. using namespace std;
  11. #define ll long long
  12. #define re register
  13. #define file(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
  14. inline int gi()
  15. {
  16. int f=1,sum=0;char ch=getchar();
  17. while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
  18. while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
  19. return f*sum;
  20. }
  21. const int N=300010;
  22. int K[N],n;
  23. struct node
  24. {
  25. int ff,ch[2],siz,rev;
  26. }t[N];
  27. int sta[N],top;
  28. void pushup(int x)
  29. {
  30. t[x].siz=t[t[x].ch[0]].siz+t[t[x].ch[1]].siz+1;
  31. }
  32. void reverse(int x)
  33. {
  34. swap(t[x].ch[0],t[x].ch[1]);
  35. t[x].rev^=1;
  36. }
  37. void pushdown(int x)
  38. {
  39. if(!t[x].rev)return;
  40. if(t[x].ch[0])reverse(t[x].ch[0]);
  41. if(t[x].ch[1])reverse(t[x].ch[1]);
  42. t[x].rev^=1;
  43. }
  44. bool isroot(int x)
  45. {
  46. return (t[t[x].ff].ch[0]!=x) && (t[t[x].ff].ch[1]!=x);
  47. }
  48. void rotate(int x)
  49. {
  50. int y=t[x].ff,z=t[y].ff;
  51. int k=t[y].ch[1]==x;
  52. if(!isroot(y))t[z].ch[t[z].ch[1]==y]=x;//只能在这一棵Splay里面Rotate
  53. t[x].ff=z;
  54. t[y].ch[k]=t[x].ch[k^1];
  55. t[t[x].ch[k^1]].ff=y;
  56. t[x].ch[k^1]=y;t[y].ff=x;
  57. pushup(y);pushup(x);
  58. }
  59. void splay(int x)
  60. {
  61. sta[++top]=x;
  62. for(int i=x;!isroot(i);i=t[i].ff)sta[++top]=t[i].ff;
  63. while(top)pushdown(sta[top--]);
  64. while(!isroot(x))
  65. {
  66. int y=t[x].ff,z=t[y].ff;
  67. if(!isroot(y))//Splay是旋转到当前这棵Splay的根,这个道理就和上面的rotate是一样的.
  68. (t[y].ch[0]==x)^(t[z].ch[0]==y)?rotate(x):rotate(y);
  69. rotate(x);
  70. }
  71. pushup(x);
  72. }
  73. void access(int x)
  74. {
  75. for(int y=0;x;y=x,x=t[x].ff)
  76. {
  77. splay(x);
  78. t[x].ch[1]=y;
  79. pushup(x);
  80. }
  81. }
  82. void makeroot(int x)
  83. {
  84. access(x);splay(x);
  85. reverse(x);
  86. }
  87. int findroot(int x)
  88. {
  89. access(x);splay(x);
  90. while(t[x].ch[0])x=t[x].ch[0];
  91. return x;
  92. }
  93. void split(int x,int y)
  94. {
  95. makeroot(x);
  96. access(y);
  97. splay(y);
  98. }
  99. void link(int x,int y)
  100. {
  101. makeroot(x);
  102. t[x].ff=y;
  103. }
  104. void cut(int x,int y)
  105. {
  106. split(x,y);
  107. t[y].ch[0]=t[x].ff=0;
  108. }
  109. int judge(int x)
  110. {
  111. return x>n?n+1:x;
  112. }
  113. int main()
  114. {
  115. n=gi();
  116. for(int i=1;i<=n;i++)
  117. t[i].siz=1;
  118. for(int i=1;i<=n;i++)
  119. link(i,judge(i+(K[i]=gi())));
  120. int Q=gi();
  121. while(Q--)
  122. {
  123. int opt=gi(),u=gi();u++;
  124. if(opt==1)
  125. {
  126. makeroot(u);access(n+1);splay(n+1);
  127. printf("%d\n",t[n+1].siz-1);
  128. }
  129. if(opt==2)
  130. {
  131. int tmp=K[u];
  132. K[u]=gi();
  133. cut(u,judge(u+tmp));
  134. link(u,judge(u+K[u]));
  135. }
  136. }
  137. return 0;
  138. }

分块

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<string.h>
  4. #include<math.h>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<iostream>
  8. using namespace std;
  9. inline int gi(){
  10. int sum=0,f=1;char ch=getchar();
  11. while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
  12. while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
  13. return f*sum;
  14. }
  15. const int N=400010;
  16. int bl[N],nxt[N],sum[N],a[N];
  17. int n,B,m;
  18. void ask(int l,int r){
  19. for(int i=r;i>=l;i--)
  20. if(i+a[i]>min(n,bl[i]*B))sum[i]=1,nxt[i]=i+a[i];
  21. else sum[i]=sum[i+a[i]]+1,nxt[i]=nxt[i+a[i]];
  22. }
  23. int main(){
  24. #ifndef ONLINE_JUDGE
  25. freopen("in.in","r",stdin);
  26. freopen("out.out","w",stdout);
  27. #endif
  28. n=gi();B=sqrt(n);
  29. for(int i=1;i<=n;i++)a[i]=gi();
  30. for(int i=1;i<=n;i++)
  31. bl[i]=(i-1)/B+1;
  32. ask(1,n);
  33. m=gi();int all=bl[n];
  34. while(m--){
  35. int opt=gi(),x=gi();x++;
  36. if(opt==1){
  37. int ans=sum[x],now=nxt[x],i=bl[x];
  38. while(now<=n && i<=all){ans+=sum[now];now=nxt[now];i++;}
  39. printf("%d\n",ans);
  40. }
  41. else{
  42. int k=gi();
  43. a[x]=k;
  44. ask((bl[x]-1)*B+1,min(bl[x]*B,n));
  45. }
  46. }
  47. return 0;
  48. }

【BZOJ2002】 [Hnoi2010]Bounce 弹飞绵羊的更多相关文章

  1. BZOJ2002 Hnoi2010 Bounce 弹飞绵羊 【LCT】【分块】

    BZOJ2002 Hnoi2010 Bounce 弹飞绵羊 Description 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始, ...

  2. [bzoj2002][Hnoi2010]Bounce弹飞绵羊_LCT

    Bounce弹飞绵羊 bzoj-2002 Hnoi-2010 题目大意:n个格子,每一个格子有一个弹簧,第i个格子会将经过的绵羊往后弹k[i]个,达到i+k[i].如果i+k[i]不存在,就表示这只绵 ...

  3. bzoj2002: [Hnoi2010]Bounce 弹飞绵羊 [分块][LCT]

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

  4. [BZOJ2002] [Hnoi2010] Bounce 弹飞绵羊 (LCT)

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

  5. [bzoj2002][Hnoi2010]Bounce弹飞绵羊——分块

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

  6. BZOJ2002: [Hnoi2010]Bounce 弹飞绵羊(LCT)

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

  7. bzoj2002 [Hnoi2010]Bounce 弹飞绵羊——分块

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2002 第一次用分块,感觉超方便啊: 如果记录每个点的弹力系数,那么是O(1)修改O(n)查询 ...

  8. bzoj2002 [Hnoi2010]Bounce 弹飞绵羊【分块】

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2002 这一题除了LCT解法,还有一种更巧妙,代码量更少的解法,就是分块.先想,如果仅仅记录每 ...

  9. 题解【bzoj2002 [Hnoi2010]Bounce 弹飞绵羊】

    Description 给 \(n\) 个点以及它们的弹力系数 \(k_i\) ,含义为 可以弹到 \(i + k_i\) 的位置. 支持两个东西,修改一个点的弹力系数:求一个点要弹多少次弹出 \(n ...

  10. 【lct】bzoj2002 [Hnoi2010]Bounce 弹飞绵羊

    lct板子,此题主要有cut操作和link操作. #include<cstdio> #include<iostream> #include<cstring> #in ...

随机推荐

  1. 2017/2/11CSS基础

    一:html中div: 1.DIV标签应用于 Style Sheet(样式表)方面会更显威力,它最终目的是给设计者另一种组织能力,有 Class.Style.title.ID 等属性. 2.<d ...

  2. 服务器重复发送SYN ACK 和 TCP_DEFER_ACCEPT设置

    现象: 以下为其他网站提供,和我遇到的情况一样. 就是服务器老是重复发送 SYN, ACK. 4414.229553  client -> server TCP 62464 > http ...

  3. zabbix实现企业微信监控报警

    一.zabbix基本说明 简介:zabbix基于Web界面的分布式系统监控的企业级开源软件.可以监控各种系统与设备,网络参数,保证服务器设备安全运营:提供灵活的通知机制.如果检测到的指标不达标,就实现 ...

  4. rails 表单中默认值

    在表单中加入默认提示值,如(email@email.com): <div class="field"> <%= form.label :email,"E ...

  5. 爬虫模块之解决IO

    一 asyncio模块 asyncio模块:主要是帮我们检测IO(只能是网路IO). @asyncio.coroutine:装饰器 tasks:任务列表 get_event_loop:起任务 run_ ...

  6. 前端之javascript的节点操作和Event

    一 节点的增删改查 创建节点:createElement(标签名):创建一个指定名称的节点. 追加节点: 追加一个子节点:somenode.appendChild(标签名) 指定某个位置前面添加一个节 ...

  7. PCA图

    R语言PCA 1.关键点 综述:主成分分析 因子分析 典型相关分析,三种方法的共同点主要是用来对数据降维处理的从数据中提取某些公共部分,然后对这些公共部分进行分析和处理. #主成分分析 是将多指标化为 ...

  8. 2018.12.15 spoj1812 Longest Common Substring(后缀自动机)

    传送门 后缀自动机模板题. 题意简述:求两个字串的最长公共子串长度. 对其中一个构建后缀自动机,用另外一个在上面跑即可. 代码: #include<bits/stdc++.h> #defi ...

  9. vue+mui轮播图

    mui的轮播图,如果图片是请求来的,直接在html中循环是不会动的. 需要请求完图片之后,在setTimeout方法里,使用slider()方法,这样才会动 而且mui的轮播图,有点坑的,需要重复最后 ...

  10. 快速创建一个 Servlet 项目(2)

    1. 新建一个 webapp 参考 http://www.cnblogs.com/zno2/p/5909019.html 2.调整jdk版本 修改 pom.xml 文件,将jdk 调整为适当的版本,比 ...