某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏。游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹ki步,达到第i+ki个装置,若不存在第i+ki个装置,则绵羊被弹飞。绵羊想知道当它从第i个装置起步时,被弹几次后会被弹飞。为了使得游戏更有趣,Lostmonkey可以修改某个弹力装置的弹力系数,任何时候弹力系数均为正整数。
某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏。游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹ki步,达到第i+ki个装置,若不存在第i+ki个装置,则绵羊被弹飞。绵羊想知道当它从第i个装置起步时,被弹几次后会被弹飞。为了使得游戏更有趣,Lostmonkey可以修改某个弹力装置的弹力系数,任何时候弹力系数均为正整数。
第一行包含一个整数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
对于每个i=1的情况,你都要输出一个需要的步数,占一行。
3
将N个装置从左到右分为sqrt(N)段,维护两个数组,f[i][j]表示第I段的第J个位置开始在该段弹多少次,to[i][j]表示第I段的第J个位置弹飞到哪个位置。
每次询问,跑sqrt(N)个段。
每次更新,比如修改i点,只需要更新与i同段且在i左边的f[][]和to[][]
复杂度为N*sqrt(N)
#include
#include
#include
#include
using namespace std;
#define maxn 200080
#define maxm 508
int f[maxm][maxm];//第I快,第J个位置,跳多少次
int to[maxm][maxm];//第I快,第J个位置,跳到哪个位置
int a[maxn];
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int n;
while(scanf("%d",&n)!=EOF)
{
for(int i = 1;i <= n;i++)
scanf("%d",&a[i]);
int len = sqrt(double(n))+1;
int num = n/len;
if(n%len) num++;
for(int i = num;i >= 1;i--)
{
for(int j = len;j >= 1;j--)
{
int pos = (i-1)*len+j;
if(pos>n)
{
f[i][j] = 0;
to[i][j] = pos;
continue;
}
if(j+a[pos]<=len)
{
f[i][j] = f[i][j+a[pos]]+1;
to[i][j] = to[i][j+a[pos]];
}
else
{
f[i][j] = 1;
to[i][j] = pos+a[pos];
}
}
}
int m;
scanf("%d",&m);
for(int i = 1;i <= m;i++)
{
int ope,p,k;
scanf("%d%d",&ope,&p);
p++;
if(ope == 1)
{
int ans = 0;
while(p <= n)
{
ans += f[(p+len-1)/len][(p%len)?(p%len):len];
p = to[(p+len-1)/len][(p%len)?(p%len):len] ;
}
printf("%d\n",ans);
}
else
{
scanf("%d",&k);
a[p] = k;
int index = p%len?p%len:len;
for(int j = index;j >= 1;j--)
{
f[(p+len-1)/len][j] = (j+a[p+j-index]>len?1:(f[(p+len-1)/len][j+a[p+j-index]]+1));
to[(p+len-1)/len][j] = (j+a[p+j-index]>len?p+j-index+a[p+j-index] : to[(p+len-1)/len][j+a[p+j-index]]);
}
}
}
}
return 0;
}
#include
#include
#include
using namespace std;
#define maxn 200080
#define inf 0x3f3f3f3f
int a[maxn],stk[maxn];
int e,n;
struct Link_Cut_Tree
{
int pre[maxn],ch[maxn][2],flip[maxn];
int root[maxn],fa[maxn],Size[maxn];
void init()
{
root[0] = Size[0] = ch[0][0] = ch[0][1] = pre[0] = flip[0] = fa[0] = 0;
}
void NewNode(int r,int father)
{
root[r] = 1;
Size[r] = 1;
fa[r] = father;
ch[r][0] = ch[r][1] = flip[r] = pre[r] = 0;
}
void PushTo(int x)
{
int rear = 0;
while(x)
{
stk[rear++] = x;
x = pre[x];
}
for(int i = rear-1;i >= 0;i--)
PushDown(stk[i]);
}
void PushDown(int x)
{
if(flip[x])
{
Update_Rev(ch[x][0]);
Update_Rev(ch[x][1]);
flip[x] = 0;
}
}
void PushUp(int x)
{
int l = ch[x][0],r = ch[x][1];
Size[x] = Size[l] + Size[r] + 1;
}
void Update_Rev(int x)
{
swap(ch[x][0],ch[x][1]);
flip[x] ^= 1;
}
void Rotate(int x,int kind)
{
int y = pre[x];
ch[y][!kind] = ch[x][kind];
if(ch[x][kind])
pre[ch[x][kind]] = y;
if(pre[y])
ch[pre[y]][ch[pre[y]][1]==y] = x;
pre[x] = pre[y];
ch[x][kind] = y;
pre[y] = x;
PushUp(y);
if(root[y])
{
root[y] = 0;
root[x] = 1;
fa[x] = fa[y];
fa[y] = 0;
}
}
void Splay(int r)
{
PushTo(r);
while(pre[r] != 0)
{
int y = pre[r],z = pre[y];
if(z == 0)
{
Rotate(r,ch[y][0]==r);
}
else
{
int kind = (ch[z][0] == y);
if(ch[y][kind] == r)
{
Rotate(r,!kind);
Rotate(r,kind);
}
else
{
Rotate(y,kind);
Rotate(r,kind);
}
}
}
PushUp(r);
}
int Access(int x)
{
int c = 0;
while(x)
{
Splay(x);
if(ch[x][1])
{
fa[ch[x][1]] = x;
Is_Root(ch[x][1]);
}
ch[x][1] = c;
if(c)
{
pre[c] = x;
fa[c] = 0;
}
root[c] = 0;
c = x; x = fa[x];
}
return c;
}
void Make_Root(int x)
{
Access(x);
Splay(x);
Update_Rev(x);
}
void Is_Root(int x)
{
root[x] = 1;
pre[x] = 0;
}
void Link(int u,int v)
{
if(u == v) return;
Make_Root(u);
Access(v);
Splay(v);
if(pre[u] == 0) fa[u] = v;
}
void Cut(int u,int v)
{
Make_Root(u);
Access(v);
Splay(v);
if(pre[u])
{
if(ch[v][0])
Is_Root(ch[v][0]);
fa[ch[v][0]] = 0;
ch[v][0] = 0;
Is_Root(v);
fa[v] = 0;
PushUp(v);
}
}
int Query(int u)
{
Make_Root(n+1);
Access(u);
Splay(u);
return Size[ch[u][0]];
}
void solve()
{
for(int i = 1;i <= n;i++)
scanf("%d",&a[i]);
int q;
scanf("%d",&q);
init();
NewNode(n+1,0);
for(int i = n;i >= 1;i--)
{
int u = i,v = i+a[i] > n? n+1:i+a[i];
NewNode(u,v);
}
while(q--)
{
int ope,pos,k;
scanf("%d%d",&ope,&pos);
pos++;
if(ope == 1)
{
printf("%d\n",Query(pos));
}
else
{
scanf("%d",&k);
int apre = a[pos]+pos>n?n+1:a[pos]+pos;
Cut(pos,apre);
a[pos] = k;
int anow = a[pos]+pos>n?n+1:a[pos]+pos;
Link(pos,anow);
}
}
}
}lct;
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
while(scanf("%d",&n)!=EOF)
{
lct.solve();
}
}