LCT 裸題,技巧是反着建邊才能維護向下路徑
/**************************************************************
Problem: 2002
User: Clare
Language: C++
Result: Accepted
Time:1884 ms
Memory:6036 kb
****************************************************************/
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#include <vector>
#include <stack>
using namespace std;
#define N 200010
int n,m;
int size[N],fa[N],c[N][2],Next[N];
bool Rev[N];
stack<int> st;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
void Pushup(int k)
{
int l=c[k][0],r=c[k][1];
size[k]=size[l]+size[r]+1;
}
void Pushdown(int k)
{
int l=c[k][0],r=c[k][1];
if(Rev[k])
{
Rev[k]^=1;Rev[r]^=1;Rev[l]^=1;
swap(c[k][0],c[k][1]);
}
}
bool Pd_root(int k)
{
return !(c[fa[k]][0]==k)&&!(c[fa[k]][1]==k);
}
void Rotate(int x)
{
int y=fa[x],z=fa[y],l,r;
if(c[y][0]==x)l=0;else l=1;
r=l^1;
if(Pd_root(y));
else if(c[z][0]==y)c[z][0]=x;
else c[z][1]=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)
{
st.push(x);
for(int i=x;!Pd_root(i);i=fa[i])
{
st.push(fa[i]);
}
while(!st.empty())
{
int now=st.top();st.pop();
Pushdown(now);
}
while(!Pd_root(x))
{
int y=fa[x],z=fa[y];
if(!Pd_root(y))
{
if(c[y][0]==x^c[z][0]==y)
Rotate(x);
else Rotate(y);
}
Rotate(x);
}
}
void Access(int x)
{
for(int t=0;x;t=x,x=fa[x])
Splay(x),c[x][1]=t,Pushup(x);
}
void Move_to_root(int x)
{
Access(x);Splay(x);Rev[x]^=1;
}
void Join(int x,int y)
{
Move_to_root(x);fa[x]=y;
}
void Cut(int x,int y)
{
Move_to_root(x);Access(y);Splay(y);
fa[x]=0;c[y][0]=0;
Pushup(y);
}
void Split(int x,int y)
{
Move_to_root(x);Access(y);Splay(y);
}
int main()
{
n=read();
for(int i=1;i<=n+1;i++)
size[i]=1;
for(int i=1;i<=n;i++)
{
int x=read();
if(i+x>n)
fa[i]=n+1,Next[i]=n+1;
else fa[i]=i+x,Next[i]=i+x;
}
m=read();
for(int i=1;i<=m;i++)
{
int kind=read();
if(kind==1)
{
int x=read()+1;
Move_to_root(n+1);Access(x);Splay(x);
printf("%d\n",size[c[x][0]]);
}
else
{
int x=read()+1,y=read();
if(x+y>n)
y=n+1;
else y=x+y;
Cut(x,Next[x]);Join(x,y);
Next[x]=y;
}
}
return 0;
}