BZOJ2002 Hnoi2010 Bounce 弹飞绵羊


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


分块做法和LCT做法都有

先讲讲LCT,就是一个板子,把当前点和可以连到的点连边,然后修改弹力值就是把边断开然后重新连一条边,维护的答案是一条链的长度,在这里可以直接用LCT的性质直接维护siz

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define N 200010
  4. #define INF 1e9
  5. inline int read(){
  6. int res=0,w=1;char c=getchar();
  7. while(!isdigit(c)&&c!='-')c=getchar();
  8. if(c=='-')w=-1,c=getchar();
  9. while(isdigit(c))res=(res<<1)+(res<<3)+c-'0',c=getchar();
  10. return res;
  11. }
  12. struct Link_Cut_Tree{
  13. int fa[N],son[N][2],siz[N];bool rev[N];
  14. Link_Cut_Tree(){memset(rev,0,sizeof(rev));}
  15. bool isroot(int t){return son[fa[t]][0]!=t&&son[fa[t]][1]!=t;}
  16. bool Son(int t){return son[fa[t]][1]==t;}
  17. void pushup(int t){siz[t]=siz[son[t][0]]+siz[son[t][1]]+1;}
  18. void pushdown(int t){
  19. if(!isroot(t))pushdown(fa[t]);
  20. if(rev[t]){
  21. rev[t]^=1;
  22. rev[son[t][0]]^=1;
  23. rev[son[t][1]]^=1;
  24. swap(son[t][0],son[t][1]);
  25. }
  26. }
  27. void rotate(int t){
  28. int f=fa[t],g=fa[f];
  29. bool a=Son(t),b=a^1;
  30. if(!isroot(f))son[g][Son(f)]=t;fa[t]=g;
  31. son[f][a]=son[t][b];fa[son[t][b]]=f;
  32. son[t][b]=f;fa[f]=t;
  33. pushup(f);pushup(t);
  34. }
  35. void splay(int t){
  36. pushdown(t);
  37. while(!isroot(t)){
  38. int f=fa[t];
  39. if(!isroot(f)){
  40. if(Son(t)^Son(f))rotate(t);
  41. else rotate(f);
  42. }
  43. rotate(t);
  44. }
  45. }
  46. void access(int t){
  47. int tmp=0;
  48. while(t){
  49. splay(t);
  50. son[t][1]=tmp;
  51. if(tmp)fa[tmp]=t;pushup(t);
  52. tmp=t;t=fa[t];
  53. }
  54. }
  55. void putroot(int t){
  56. access(t);
  57. splay(t);
  58. rev[t]^=1;
  59. }
  60. void link(int x,int y){putroot(x);fa[x]=y;}
  61. void cut(int x,int y){
  62. putroot(x);
  63. access(y);
  64. splay(y);
  65. son[y][0]=fa[x]=0;
  66. pushup(y);
  67. }
  68. int query(int x,int y){
  69. putroot(y);
  70. access(x);
  71. splay(x);
  72. return siz[x]-1;
  73. }
  74. }lct;
  75. int n,m,a[N];
  76. int main(){
  77. n=read();
  78. for(int i=1;i<=n;i++)a[i]=read();
  79. for(int i=1;i<=n;i++)
  80. lct.link(i,(i+a[i]>n)?n+1:i+a[i]);
  81. m=read();
  82. for(int i=1;i<=m;i++){
  83. int op,x,y;
  84. scanf("%d",&op);
  85. if(op==1){
  86. scanf("%d",&x);x++;
  87. printf("%d\n",lct.query(x,n+1));
  88. }else{
  89. scanf("%d%d",&x,&y);x++;
  90. lct.cut(x,(x+a[x]>n)?n+1:x+a[x]);
  91. a[x]=y;
  92. lct.link(x,(x+a[x]>n)?n+1:x+a[x]);
  93. }
  94. }
  95. return 0;
  96. }

然后讲讲分块,每次暴力跳,维护一下每个点跳出当前块的操作次数,暴力修改暴力查询就好了

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define INF 0x7fffffff
  4. #define LL long long
  5. #define N 1000010
  6. const int siz=1000;
  7. struct Temp{int to,tmp,bel;}a[N];
  8. int n,m,pre[N];
  9. int read(){
  10. int ans=0,w=1;char c=getchar();
  11. while(!isdigit(c)&&c!='-')c=getchar();
  12. if(c=='-')c=getchar(),w=-1;
  13. while(isdigit(c))ans=ans*10+c-'0',c=getchar();
  14. return ans*w;
  15. }
  16. void modify(int x){
  17. if(a[x+pre[x]].bel!=a[x].bel){
  18. a[x].to=x+pre[x];
  19. a[x].tmp=1;
  20. }else{
  21. a[x].to=a[x+pre[x]].to;
  22. a[x].tmp=a[x+pre[x]].tmp+1;
  23. }
  24. return;
  25. }
  26. void build(){
  27. for(int i=1;i<=n;i++)a[i].bel=(i-1)/siz+1;
  28. for(int i=n;i>=1;i--)
  29. if(i+pre[i]>n)a[i].tmp=1,a[i].to=0;
  30. else modify(i);
  31. }
  32. int query(int x){
  33. int ans=0;
  34. while(x){
  35. ans+=a[x].tmp;
  36. x=a[x].to;
  37. }
  38. return ans;
  39. }
  40. int main(){
  41. n=read();
  42. for(int i=1;i<=n;i++)pre[i]=read();
  43. build();
  44. m=read();
  45. for(int i=1;i<=m;i++){
  46. int op=read(),x;
  47. if(op==1){
  48. x=read()+1;
  49. printf("%d\n",query(x));
  50. }else{
  51. x=read()+1,pre[x]=read();
  52. int fro=(a[x].bel-1)*siz+1;
  53. for(int i=x;i>=fro;i--)modify(i);
  54. }
  55. }
  56. return 0;
  57. }

BZOJ2002 Hnoi2010 Bounce 弹飞绵羊 【LCT】【分块】的更多相关文章

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

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

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

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

  3. [BZOJ2002][Hnoi2010]Bounce弹飞绵羊 LCT

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2002 建图,每次往后面跳就往目标位置连边,将跳出界的点设为同一个点.对于修改操作发现可以用 ...

  4. BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊 【分块】

    任意门:https://www.lydsy.com/JudgeOnline/problem.php?id=2002 2002: [Hnoi2010]Bounce 弹飞绵羊 Time Limit: 10 ...

  5. 2002: [Hnoi2010]Bounce 弹飞绵羊(分块)

    2002: [Hnoi2010]Bounce 弹飞绵羊 时间限制: 10 Sec  内存限制: 259 MB 题目描述 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他 ...

  6. BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊 LCT

    2002: [Hnoi2010]Bounce 弹飞绵羊 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOn ...

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

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

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

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

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

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

随机推荐

  1. u-boot-2015.07 make xxx_config 分析

    1.u-boot编译脚本:mk.sh #! /bin/sh export PATH=$PATH:/opt/ti-sdk-am335x-evm-08.00.00.00/linux-devkit/sysr ...

  2. webstorm自动换行

    1.文件 — — 设置 2. 编辑器 — — 编辑器 — — 在编辑窗口使用软换行(勾选)

  3. LeetCode第[88]题(Java):Merge Sorted Array(合并已排序数组)

    题目:合并已排序数组 难度:Easy 题目内容: Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as ...

  4. [PostgreSQL]PostgreSQL数据类型格式化函数——字符串和数值间的转换

    详情见官网:http://www.postgres.cn/docs/10/functions-formatting.html PostgreSQL中有以下格式化函数: 函数 返回类型 描述 例子 to ...

  5. javascript中对变量类型的判断

    本文正式地址:http://www.xiabingbao.com/javascript/2015/07/04/javascript-type 在JavaScript中,有5种基本数据类型和1种复杂数据 ...

  6. python selenium常用基本方法---H5和键盘鼠标操作

    一.模拟手机打开页面(H5测试) from selenium import webdriver mobile_emulation = {'deviceName':'iPhone X'} options ...

  7. 如何在Ubuntu Linux上安装Oracle Java

    不错文档,希望地址永久可用,url:http://zh.wikihow.com/%E5%9C%A8Ubuntu-Linux%E4%B8%8A%E5%AE%89%E8%A3%85Oracle-Java

  8. Codeforces Round #423

    这一次又崩了,最后只a了一题(还是被hack后才发现的错误) 第一题水题,多用一个数保存2-1后的数,注意先用2的桌子,再用这个 #include<map> #include<set ...

  9. 【Python】装饰器理解

    以下文章转载自:点这里 关于装饰器相关的帖子记录在这里: 廖雪峰, thy专栏, stackflow Python的函数是对象 简单的例子: def shout(word="yes" ...

  10. [Android]如何减小APK的大小

    能不引用的外部包就不用,删除没用的图片.xml,优化代码去掉没用的部分,能异步下载的资源就运行时从网络上下载.