题目
做法
本来以为是个水题,其实还是有思维性的
(LCT)上操作和模板一样,显然我们维护子树大小
开始是想(Link(x,x+val[x]))当(x+val[x]>n)时就不连,然后查询(x)时就查询右子树大小
反例就不举了随手就是个反例吧反正这种办法是错的
正解:(Link(x,x+val[x]))当(x+val[x]>n)时(Link(x,n+1))
查询(x)时其实就是查询(x)~(n+1)这条链:(Makeroot(x); Access(n+1); Splay(n+1);),输出(size[n+1]-1)
My complete code
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<string>
#include<cmath>
#include<stack>
using namespace std;
typedef int LL;
const LL maxn=1e6;
inline LL Read(){
LL x(0),f(1);char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-'0',c=getchar();
return x*f;
}
LL n,m;
LL size[maxn],fa[maxn],son[maxn][2],r[maxn],val[maxn];
inline bool Notroot(LL x){
return (son[fa[x]][0]==x||son[fa[x]][1]==x);
}
inline void Pushr(LL x){
swap(son[x][0],son[x][1]);r[x]^=1;
}
inline void Pushdown(LL x){
if(r[x]){
if(son[x][0])Pushr(son[x][0]);
if(son[x][1])Pushr(son[x][1]);
r[x]^=1;
}
}
inline void Update(LL x){
size[x]=1+size[son[x][0]]+size[son[x][1]];
}
inline void Rotate(LL x){
LL y(fa[x]),z(fa[y]),lz=(son[y][1]==x);
if(Notroot(y))
son[z][son[z][1]==y]=x;
fa[x]=z;
son[y][lz]=son[x][lz^1];
if(son[y][lz])
fa[son[y][lz]]=y;
son[x][lz^1]=y;fa[y]=x;
Update(y),Update(x);
}
LL sta[maxn];
inline void Splay(LL x){
LL y(x),top(0);
sta[++top]=y;
while(Notroot(y)) sta[++top]=y=fa[y];
while(top) Pushdown(sta[top--]);
while(Notroot(x)){
y=fa[x];
if(Notroot(y)){
LL z=fa[y];
if(((son[z][1]==y)^(son[y][1]==x))==0) Rotate(y);
else Rotate(x);
}
Rotate(x);
}
}
inline void Access(LL x){
for(LL y=0;x;y=x,x=fa[x]){
Splay(x),son[x][1]=y;Update(x);
}
}
inline void Makeroot(LL x){
Access(x),Splay(x),Pushr(x);
}
inline void Split(LL x,LL y){
Makeroot(x),Access(y),Splay(y);
}
inline void Link(LL x,LL y){
Makeroot(y);
fa[y]=x;
}
inline void Delet(LL x,LL y){
Split(x,y);
fa[x]=son[y][0]=0;
Update(y);
}
int main(){
n=Read();
for(LL i=1;i<=n;++i) size[i]=1;
for(LL i=1;i<=n;++i){
val[i]=Read();
if(i+val[i]<=n)
Link(i,i+val[i]);
else
Link(i,n+1);
}
m=Read();
while(m--){
LL op(Read());
if(op==1){
LL x(Read()+1);
Makeroot(x); Access(n+1); Splay(n+1);
printf("%d
",size[n+1]-1);
}else{
LL x(Read()+1),y(Read());
if(x+val[x]<=n) Delet(x,x+val[x]);
else Delet(x,n+1);
val[x]=y;
if(x+val[x]<=n) Link(x,x+val[x]);
else Link(x,n+1);
}
}
}