某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏。游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹ki步,达到第i+ki个装置,若不存在第i+ki个装置,则绵羊被弹飞。绵羊想知道当它从第i个装置起步时,被弹几次后会被弹飞。为了使得游戏更有趣,Lostmonkey可以修改某个弹力装置的弹力系数,任何时候弹力系数均为正整数。
水题已经越来越少了呢
首先发现所有路径组成一个树的结构,每次修改相当于移动一整棵子树
直接\(LCT\)维护即可
发现距离就是链的\(siz-1\),直接\(access\)一下就行
#include<bits/stdc++.h>
#define ll long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)>(b)?(b):(a))
#define reg register
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
const int MN=2e5+5;
class Link_Cut_Tree
{
int c[MN][2],fa[MN],siz[MN];
bool get(int x){return c[fa[x]][1]==x;}
bool nrt(int x){return c[fa[x]][0]==x||c[fa[x]][1]==x;}
void up(int x){siz[x]=siz[c[x][1]]+siz[c[x][0]]+1;}
int rtt(int x)
{
int y=fa[x],z=fa[y],l=get(x),r=l^1;if(nrt(y))c[z][get(y)]=x;fa[x]=z;
fa[c[x][r]]=y;c[y][l]=c[x][r];c[x][r]=y;fa[y]=x;up(y);
}
void Splay(int x)
{
for(;nrt(x);rtt(x))
if(nrt(fa[x])) rtt(get(x)^get(fa[x])?x:fa[x]);
up(x);
}
void acs(int x){for(reg int i=0;x;x=fa[i=x])Splay(x),c[x][1]=i,up(x);}
public:
void init(int N){for(reg int i=1;i<=N+1;++i)siz[i]=1;}
void link(int x,int y){fa[x]=y;}
void cut(int x){acs(x);Splay(x);fa[c[x][0]]=0;c[x][0]=0;up(x);}
int que(int x){acs(x);Splay(x);return siz[x]-1;}
}T;
int k[MN];
int main()
{
reg int i,N,M;N=read();T.init(N);
for(i=1;i<=N;++i) k[i]=read(),T.link(i,min(i+k[i],N+1));
M=read();
while(M--)
{
i=read();
if(i==1) printf("%d\n",T.que(read()+1));
else i=read()+1,T.cut(i),k[i]=read(),T.link(i,min(i+k[i],N+1));
}
return 0;
}
Blog来自PaperCloud,未经允许,请勿转载,TKS!
原文:https://www.cnblogs.com/PaperCloud/p/10660135.html