• 【bzoj 2002】弹飞绵羊


    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

     

    唉隔壁都在弹飞大爷了,我还在弹绵羊>_<

     

    分块大法【Time:1472 ms】

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<cmath>
     5 using namespace std;
     6 const int N=200050;
     7 int n,m,num,pl,w,bl,cnt;
     8 int k[N],be[N],st[N],to[N];
     9 int read()
    10 {
    11     int x=0,f=1;char c=getchar();
    12     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    13     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    14     return x*f;
    15 }
    16 int ask(int t)
    17 {
    18     int ans=st[t];
    19     while(to[t]<=n)
    20     {
    21         t=to[t];
    22         ans+=st[t];
    23     }
    24     return ans;
    25 }
    26 int main()
    27 {
    28     n=read();bl=sqrt(n);
    29     if(n%bl)cnt=n/bl+1;
    30     else cnt=n/bl;
    31     for(int i=1;i<=n;i++)
    32     {
    33         k[i]=read();
    34         be[i]=(i-1)/bl+1;
    35     }
    36     for(int i=n;i>0;i--)
    37     {
    38         if(be[i]==be[i+k[i]]){st[i]=st[i+k[i]]+1;to[i]=to[i+k[i]];}
    39         else {st[i]=1;to[i]=i+k[i];}
    40     }
    41     m=read();
    42     while(m--)
    43     {
    44         num=read();pl=read()+1;
    45         if(num==1)printf("%d
    ",ask(pl));
    46         else
    47         {
    48             w=read();
    49             k[pl]=w;
    50             int l=(be[pl]-1)*bl+1;
    51             for(int i=pl;i>=l;i--)
    52             {
    53                 if(be[i]==be[i+k[i]]){st[i]=st[i+k[i]]+1;to[i]=to[i+k[i]];}
    54                 else {st[i]=1;to[i]=i+k[i];}
    55             }
    56         }
    57     }
    58     return 0;
    59 }
    View Code

     

    LCT【Time:1844 ms】

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 const int N=200050;
     6 int n,m,c[N][2],next[N],fa[N],size[N],st[N];
     7 bool rev[N];
     8 int read()
     9 {
    10     int x=0,f=1;char c=getchar();
    11     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    12     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    13     return x*f;
    14 }
    15 bool isroot(int k){return c[fa[k]][0]!=k&&c[fa[k]][1]!=k;}
    16 void up(int x){size[x]=size[c[x][0]]+size[c[x][1]]+1;}
    17 void down(int x)
    18 {
    19     int l=c[x][0],r=c[x][1];
    20     if(rev[x]){rev[x]^=1;rev[l]^=1;rev[r]^=1;swap(c[x][0],c[x][1]);}
    21 }
    22 void rotate(int x)
    23 {
    24     int y=fa[x],z=fa[y],l,r;
    25     if(c[y][0]==x)l=0;else l=1;r=l^1;
    26     if(!isroot(y)){if(c[z][0]==y)c[z][0]=x;else c[z][1]=x;}
    27     fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
    28     c[y][l]=c[x][r];c[x][r]=y;
    29     up(y);up(x);
    30 }
    31 void splay(int x)
    32 {
    33     int top=0;st[++top]=x;
    34     for(int i=x;!isroot(i);i=fa[i])st[++top]=fa[i];
    35     for(int i=top;i;i--)down(st[i]);
    36     while(!isroot(x))
    37     {
    38         int y=fa[x],z=fa[y];
    39         if(!isroot(y))
    40         {
    41             if((c[y][0]==x)^(c[z][0]==y))rotate(x);
    42             else rotate(y);
    43         }
    44         rotate(x);
    45     }
    46 }
    47 void acs(int x)
    48 {
    49     int t=0;
    50     while(x){splay(x);c[x][1]=t;t=x;x=fa[x];}
    51 }
    52 void mkroot(int x)
    53 {
    54     acs(x);splay(x);rev[x]^=1;
    55 }
    56 void link(int x,int y)
    57 {
    58     mkroot(x);fa[x]=y;splay(x);
    59 }
    60 void cut(int x,int y)
    61 {
    62     mkroot(x);acs(y);splay(y);c[y][0]=fa[x]=0;
    63 }
    64 int main()
    65 {
    66     n=read();
    67     for(int i=1;i<=n;i++)
    68     {
    69         int x=read();
    70         fa[i]=x+i;size[i]=1;
    71         if(fa[i]>n+1)fa[i]=n+1;
    72         next[i]=fa[i];
    73     }
    74     size[n+1]=1;
    75     m=read();
    76     while(m--)
    77     {
    78         int f=read();
    79         if(f==1)
    80         {
    81             mkroot(n+1);
    82             int x=read()+1;
    83             acs(x);splay(x);printf("%d
    ",size[c[x][0]]);
    84         }
    85         else
    86         {
    87             int x=read()+1,y=read();
    88             int t=min(n+1,x+y);
    89             cut(x,next[x]);link(x,t);next[x]=t;
    90         }
    91     }
    92     return 0;
    93 }
    View Code
  • 相关阅读:
    [APIO2014]序列分割
    [HNOI2014]世界树
    [THUWC2017]随机二分图
    快乐游戏鸡
    [SHOI2014]三叉神经树
    带花树学习笔记
    最小树形图——朱刘算法学习笔记
    【WC2018】即时战略
    [HNOI2015]接水果
    [HAOI2018]染色
  • 原文地址:https://www.cnblogs.com/zsnuo/p/7072091.html
Copyright © 2020-2023  润新知