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
/*
求每棵子树的节点数。
这个题很巧妙的是建立了一个n+1节点,但是不太清楚这个n+1节点在程序中起了什么作用。。。
*/
#include<iostream>
#include<cstdio>
#define N 200010
using namespace std;
int n,m;
int next[N],c[N][],fa[N],size[N],st[N];
bool rev[N];
bool isroot(int k){
return c[fa[k]][]!=k&&c[fa[k]][]!=k;
}
void pushup(int x){
size[x]=size[c[x][]]+size[c[x][]]+;
}
void pushdown(int k){
int l=c[k][],r=c[k][];
if(rev[k]){
rev[k]^=;rev[l]^=;rev[r]^=;
swap(c[k][],c[k][]);
}
}
void rotate(int x){
int y=fa[x],z=fa[y],l,r;
if(c[y][]==x)l=;else l=;r=l^;
if(!isroot(y)){
if(c[z][]==y)c[z][]=x;else c[z][]=x;
}
fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
c[y][l]=c[x][r];c[x][r]=y;
pushup(y);pushup(x);
}
void splay(int x){
int top=;st[++top]=x;
for(int i=x;!isroot(i);i=fa[i])
st[++top]=fa[i];
for(int i=top;i;i--)pushdown(st[i]);
while(!isroot(x)){
int y=fa[x],z=fa[y];
if(!isroot(y)){
if(c[y][]==x^c[z][]==y)rotate(x);
else rotate(y);
}
rotate(x);
}
}
void access(int x){
int t=;
while(x){
splay(x);
c[x][]=t;
t=x;x=fa[x];}
}
void rever(int x){
access(x);splay(x);rev[x]^=;
}
void link(int x,int y){
rever(x);fa[x]=y;splay(x);
}
void cut(int x,int y){
rever(x);access(y);splay(y);c[y][]=fa[x]=;
}
int main(){
scanf("%d",&n);
for(int i=;i<=n;i++){
int x;scanf("%d",&x);
fa[i]=x+i;size[i]=;
if(fa[i]>n+)fa[i]=n+;
next[i]=fa[i];
}
size[n+]=;
scanf("%d",&m);
for(int i=;i<=m;i++){
int f;scanf("%d",&f);
if(f==){
rever(n+);
int x;scanf("%d",&x);x++;
access(x);splay(x);printf("%d\n",size[c[x][]]);
}
else {
int x,y;scanf("%d%d",&x,&y);x++;
int t=min(n+,x+y);
cut(x,next[x]);link(x,t);next[x]=t;
}
}
return ;
}
/*
如果没有修改操作,可能会想预处理出在每个点被弹飞的步数,这样的查询是O(1)的,但由于有修改操作,
使每次操作的复杂度可能变成O(n),所以可以考虑一种折中的方法,分块!
对于每一块,处理出每个点跳出这个块的步数以及会落在哪一个点上,这样使查询和修改都变成了O(√n)。
*/
#include<cstdio>
#include<iostream>
#include<cmath>
#define N 200010
using namespace std;
int k[N],bl[N],stp[N],next[N],n,m,len;
void init(int x){
for(int i=(x-)*len+;i<=min(x*len,n);i++){
int tot=,pos=i;
while(pos<=n&&bl[pos]==x){
tot++;
pos+=k[pos];
}
stp[i]=tot;next[i]=pos;
}
}
int query(int x){
int ans=;
for(int i=x;i<=n;i=next[i])
ans+=stp[i];
return ans;
}
void modify(int x,int y){
k[x]=y;
for(int i=x;i>=(bl[x]-)*len+;i--){
if(i+k[i]>bl[x]*len) stp[i]=,next[i]=i+k[i];
else stp[i]=stp[i+k[i]]+,next[i]=next[i+k[i]];
}
}
int main(){
scanf("%d",&n);len=sqrt(n);
for(int i=;i<=n;i++){
scanf("%d",&k[i]);
bl[i]=(i-)/len+;
}
for(int i=;i<=bl[n];i++)
init(i);
scanf("%d",&m);
for(int i=;i<=m;i++){
int opt,x,y;scanf("%d%d",&opt,&x);x++;
if(opt==) printf("%d\n",query(x));
else scanf("%d",&y),modify(x,y);
}
return ;
}

弹飞绵羊(bzoj 2002)的更多相关文章

  1. 2002: [Hnoi2010]Bounce 弹飞绵羊 - BZOJ

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

  2. Bounce 弹飞绵羊 HYSBZ - 2002 分块

    //预处理出以这个点为起点并跳出这个块的次数和位置 //更新一个点的弹力系数可以只更新这个点以及这个块内之前的点 #include<stdio.h> #include<algorit ...

  3. bzoj 2002 Bounce 弹飞绵羊

    bzoj 2002 Bounce 弹飞绵羊 设一个虚拟节点表示被弹飞,则每个点的后继点是唯一确定的,每个点向它的后继点连边,就形成了一颗树. 询问就是问某个节点到虚拟节点的路径长度,修改就删除原来向后 ...

  4. [BZOJ 2002] [HNOI2010]弹飞绵羊(Link Cut Tree)

    [BZOJ 2002] [HNOI2010]弹飞绵羊(Link Cut Tree) 题面 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一 ...

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

    2002: [Hnoi2010]Bounce 弹飞绵羊 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 9071  Solved: 4652[Submi ...

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

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

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

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

  8. bzoj 2002: [Hnoi2010]Bounce 弹飞绵羊 動態樹

    2002: [Hnoi2010]Bounce 弹飞绵羊 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 4055  Solved: 2172[Submi ...

  9. bzoj 2002 : [Hnoi2010]Bounce 弹飞绵羊 (LCT)

    链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2002 题面: 2002: [Hnoi2010]Bounce 弹飞绵羊 Time Limit: ...

  10. BZOJ 2002:Bounce 弹飞绵羊(分块)

    2002: [Hnoi2010]Bounce 弹飞绵羊 Time Limit: 10 Sec  Memory Limit: 259 MB Submit: 14944  Solved: 7598 [Su ...

随机推荐

  1. hihocoder1779 公路收费

    思路: 枚举每个点做根即可. 实现: #include <bits/stdc++.h> using namespace std; typedef long long ll; const l ...

  2. jquery实现上传图片及图片大小验证、图片预览效果代码

    jquery实现上传图片及图片大小验证.图片预览效果代码 jquery实现上传图片及图片大小验证.图片预览效果代码 上传图片验证 */ function submit_upload_picture() ...

  3. 类似QQ在线离线好友界面

    把头像设置成圆形的代码如下: package com.example.lesson6_11_id19; import android.content.Context; import android.c ...

  4. javascript动态添加、修改、删除对象的属性与方法

    在其他语言中,对象一旦生成,就不可更改了,要为一个对象添加修改成员必须要在对应的类中修改,并重新实例化,而且程序必须经过重新编译.JavaScript 中却非如此,它提供了灵活的机制来修改对象的行为, ...

  5. CSS 循环动画效果。

    @-moz-keyframes revolving{ 0{ -moz-transform: rotate(0deg); -webkit-transform: rotate(0deg); } 25%{ ...

  6. socket是什么?协议栈操作的抽象

    http://www.cnblogs.com/airtcp/p/5230161.html TCP/IP只是一个协议栈,就像操作系统的运行机制一样,必须要具体实现,同时还要提供对外的操作接口.就像操作系 ...

  7. 图形学基础 | 实现OBJ文件的载入

    1. tiny_obj_loader.h 的使用include这个头文件需要先定义一个宏 #define TINYOBJLOADER_IMPLEMENTATION#include "tiny ...

  8. 光线步进——RayMarching入门

    入门实现 先用RayMarching描绘一个球体,最后在进行光照计算参考:https://www.shadertoy.com/view/llt3R4 模拟摄像机射线float3 rayDirectio ...

  9. ubuntu命令行转换图片像素大小

    convert -resize 512x256 00433.png 00001.png 1.512和256之间是x(就是字母那个x),用' * '反而会报错 2.这个命令会按照原图的比例进行转换 3. ...

  10. Windows 7桌面显示图标窗口句柄的获取

    在windows XP时代,我们获取桌面图标窗口的句柄往往用一下语句: HWND hwndParent = ::FindWindow( "Progman", "Progr ...