传送门1
传送门2
写在前面:开始种树
思路:分块 or LCT,主要结合了黄学长的模版,同时感谢char哥、Yveh、Shallwe的帮助,做法什么的建议大家还是去网上找,有很多神犇讲解得不错,蒟蒻对这种模版也说不来什么,就这样吧……
注意:找一个数组记录各个装置弹出后到的位置,以便link,cut操作
代码:
#include<bits/stdc++.h>
using namespace std;
int n,m,opt,x,y;
int stacks[200010],next[200010];
struct tree
{
int fa,ch[2],data,siz,lazy;
}a[200010];
int in()
{
int t=0;
char ch=getchar();
while (ch>'9'||ch<'0') ch=getchar();
while (ch>='0'&&ch<='9') t=t*10+ch-'0',ch=getchar();
return t;
}
bool isroot(int x)
{
return a[a[x].fa].ch[0]!=x&&a[a[x].fa].ch[1]!=x;
}
void ct(int x)
{
a[x].siz=a[a[x].ch[0]].siz+a[a[x].ch[1]].siz+1;
}
void pushdown(int x)
{
if (!a[x].lazy) return;
a[a[x].ch[0]].lazy^=1;
a[a[x].ch[1]].lazy^=1;
swap(a[x].ch[0],a[x].ch[1]);
a[x].lazy=0;
}
void rorate(int x,bool mk)
{
int y=a[x].fa;
if (!isroot(y))
{
if (a[a[y].fa].ch[0]==y) a[a[y].fa].ch[0]=x;
else a[a[y].fa].ch[1]=x;
}
a[x].fa=a[y].fa;
a[y].ch[!mk]=a[x].ch[mk];
a[a[x].ch[mk]].fa=y;
a[y].fa=x;
a[x].ch[mk]=y;
ct(y);ct(x);
}
void splay(int x)
{
int y,k=x,cnt=0;stacks[++cnt]=k;
while (!isroot(k))
stacks[++cnt]=a[k].fa,
k=a[k].fa;
for (int i=cnt;i;i--) pushdown(stacks[i]);
while (!isroot(x))
{
y=a[x].fa;
if (isroot(y))
{
int t=a[y].fa;
if (a[y].ch[0]==x) rorate(x,1);
else rorate(x,0);
a[x].fa=t;
}
else if (a[a[y].fa].ch[0]==y)
{
if (a[y].ch[0]==x) rorate(y,1);
else rorate(x,0);
rorate(x,1);
}
else
{
if (a[y].ch[1]==x) rorate(y,0);
else rorate(x,1);
rorate(x,0);
}
}
}
void access(int x)
{
for (int y=0;x;y=x,x=a[x].fa)
splay(x),
a[x].ch[1]=y,
ct(x);
}
void link(int x,int y)
{
access(x);
splay(x);
a[x].lazy^=1;
a[x].fa=y;
splay(x);
}
void cut(int x,int y)
{
access(x);
splay(x);
a[x].lazy^=1;
access(y);
splay(y);
a[y].ch[0]=a[x].fa=0;
}
main()
{
n=in();
for (int i=1;i<=n;i++)
{
x=in();
a[i].fa=min(x+i,n+1);
next[i]=a[i].fa;
a[i].siz=1;
}
ct(n+1);
m=in();
while (m--)
{
opt=in();
if (opt==1)
{
access(n+1);
splay(n+1);
a[n+1].lazy^=1;
x=in();
x++;
access(x);
splay(x);
printf("%d\n",a[a[x].ch[0]].siz);
}
else
{
x=in();y=in();
x++;
cut(x,next[x]);
next[x]=min(x+y,n+1);
link(x,next[x]);
}
}
}