zoukankan      html  css  js  c++  java
  • 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


    1 2 1 1 
    3
    1 1
    2 1 1
    1 1

    Sample Output

    2
    3

    正解:LCT或分块。

    这题一眼看上去就是LCT,但是不会写。然后A过的人告诉我是分块,想了一会儿yy出来了。。

    记录每个点跳到当前块的最后一个位置和跳到下一个块第一个位置的距离,这个从n到1递推就好。查询时每次跳一个块,所以最多跳sqrt(n)次。修改时只要修改当前点和在这个块中的前面的点,所以最多修改sqrt(n)次,那么总复杂度就是m*sqrt(n)。

     1 //It is made by wfj_2048~
     2 #include <algorithm>
     3 #include <iostream>
     4 #include <cstring>
     5 #include <cstdlib>
     6 #include <cstdio>
     7 #include <vector>
     8 #include <cmath>
     9 #include <queue>
    10 #include <stack>
    11 #include <map>
    12 #include <set>
    13 #define inf (1<<30)
    14 #define il inline
    15 #define RG register
    16 #define ll long long
    17 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
    18 
    19 using namespace std;
    20 
    21 int k[400010],bl[400010],far[400010],dis[400010],n,m,block;
    22 
    23 il int gi(){
    24     RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    25     if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x;
    26 }
    27 
    28 il void work(){
    29     n=gi(),block=sqrt(n); for (RG int i=1;i<=n;++i) k[i]=gi(),bl[i]=(i-1)/block+1; m=gi();
    30     for (RG int i=n+1;i<=2*n;++i) bl[i]=i;
    31     for (RG int i=n;i;--i)
    32     if (bl[i+k[i]]>bl[i]) far[i]=i,dis[i]=1;
    33     else far[i]=far[i+k[i]],dis[i]=dis[i+k[i]]+1;
    34     for (RG int i=1;i<=m;++i){
    35     RG int type=gi(),x=gi()+1,ans=0;
    36     if (type==1){ while (x<=n) ans+=dis[x],x=far[x]+k[far[x]]; printf("%d
    ",ans); }
    37     if (type==2){
    38         RG int K=gi(),Bl=bl[x]; k[x]=K;
    39         for (;bl[x]==Bl;--x)
    40         if (bl[x+k[x]]>bl[x]) far[x]=x,dis[x]=1;
    41         else far[x]=far[x+k[x]],dis[x]=dis[x+k[x]]+1;
    42     }
    43     }
    44     return;
    45 }
    46 
    47 int main(){
    48     File("bounce");
    49     work();
    50     return 0;
    51 }

    ps:2.19改,现在会写LCT了,弄一个LCT的代码吧。。

     1 //It is made by wfj_2048~
     2 #include <algorithm>
     3 #include <iostream>
     4 #include <cstring>
     5 #include <cstdlib>
     6 #include <cstdio>
     7 #include <vector>
     8 #include <cmath>
     9 #include <queue>
    10 #include <stack>
    11 #include <map>
    12 #include <set>
    13 #define inf (1<<30)
    14 #define il inline
    15 #define RG register
    16 #define ll long long
    17 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
    18 
    19 using namespace std;
    20 
    21 int ch[200010][2],size[200010],lazy[200010],fa[200010],st[200010],k[200010],n,m;
    22 
    23 il int gi(){
    24     RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    25     if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x;
    26 }
    27 
    28 il void pushdown(RG int x){ lazy[x]=0,lazy[ch[x][0]]^=1,lazy[ch[x][1]]^=1,swap(ch[x][0],ch[x][1]); return; }
    29 
    30 il void pushup(RG int x){ if (!x) size[x]=0; else size[x]=size[ch[x][0]]+size[ch[x][1]]+1; return; }
    31 
    32 il int isroot(RG int x){ return ch[fa[x]][0]!=x && ch[fa[x]][1]!=x; }
    33 
    34 il void rotate(RG int x){
    35     RG int y=fa[x],z=fa[y],k=(ch[y][0]==x); if (!isroot(y)) ch[z][ch[z][1]==y]=x; fa[x]=z;
    36     ch[y][k^1]=ch[x][k],fa[ch[x][k]]=y,ch[x][k]=y,fa[y]=x,pushup(y),pushup(x); return;
    37 }
    38 
    39 il void splay(RG int x){
    40     RG int top=0; st[++top]=x;
    41     for (RG int i=x;!isroot(i);i=fa[i]) st[++top]=fa[i];
    42     for (RG int i=top;i;--i) if (lazy[st[i]]) pushdown(st[i]);
    43     while (!isroot(x)){
    44     RG int y=fa[x],z=fa[y];
    45     if (!isroot(y)){
    46         if ((ch[z][0]==y)^(ch[y][0]==x)) rotate(x); else rotate(y);
    47     }
    48     rotate(x);
    49     }
    50     return;
    51 }
    52 
    53 il void access(RG int x){ RG int t=0; while (x){ splay(x),ch[x][1]=t,t=x,x=fa[x]; } return; }
    54 
    55 il void makeroot(RG int x){ access(x),splay(x),lazy[x]^=1; return; }
    56 
    57 il void link(RG int x,RG int y){ makeroot(x),fa[x]=y; return; }
    58 
    59 il void cut(RG int x,RG int y){ makeroot(x),access(y),splay(y),ch[y][0]=fa[x]=0; return; }
    60 
    61 il void work(){
    62     n=gi(); RG int type,x,y; for (RG int i=1;i<=n+1;++i) size[i]=1;
    63     for (RG int i=1;i<=n;++i) k[i]=gi(),link(i,min(i+k[i],n+1)); m=gi();
    64     for (RG int i=1;i<=m;++i){
    65     type=gi();
    66     if (type==1){ x=gi()+1,makeroot(n+1),access(x),splay(x); printf("%d
    ",size[ch[x][0]]); }
    67     if (type==2) x=gi()+1,y=gi(),cut(x,min(x+k[x],n+1)),link(x,min(x+y,n+1)),k[x]=y;
    68     }
    69     return;
    70 }
    71 
    72 int main(){
    73     File("bounce");
    74     work();
    75     return 0;
    76 }
  • 相关阅读:
    原生JS实现简易随机点名功能
    react 字父组件传值
    关于react组件传值问题
    轮波图
    烟花
    this的详解
    封装多元素多属性的链式缓冲
    留言板设计的流程,拖动窗口
    运动的小球
    运动的小球自动变键盘控制
  • 原文地址:https://www.cnblogs.com/wfj2048/p/6416562.html
Copyright © 2011-2022 走看看