弹飞绵羊——好惨一只羊
2022-03-12 18:56:54
thumb_up 1
LCT板子题
构建n+1个节点, 第n+1个表示被弹出
修改即为 link和cut同时使用
本人犯了一个极为无语的错误——主程序修改结点的时候value数组别忘了改
上代码
#include<bits/stdc++.h>
#define MAXN 200010
using namespace std;
int n,m;
int g_v[MAXN],sz[MAXN],ch[MAXN][2],fa[MAXN],flag[MAXN];
//g_v: value array, sz: size of tree, ch: child (left and right),
//fa: father,
//flag: lazy_tag
bool get(int x)
{
return (ch[fa[x]][1]==x);
}
bool isroot(int x)//judge whether node x is a root of a splay
{
return (ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x);
//认父不认子(dunno how to express in english jeese
}
void pushdown(int rt)
{//tag herediting
if(!rt||!flag[rt])
return;
if(ch[rt][0])//left child exists
flag[ch[rt][0]]^=1;
if(ch[rt][1])//right child exists
flag[ch[rt][1]]^=1;
flag[rt]^=1;
swap(ch[rt][0],ch[rt][1]);//exchange position of sons(left and right)
}
void push_up(int x)
{
sz[x]=1;
if(ch[x][0])
sz[x]+=sz[ch[x][0]];
if(ch[x][1])
sz[x]+=sz[ch[x][1]];
//recalculate size of subtrees
}
void turn(int x)
{
int y=fa[x],z=fa[y],k=get(x);
//y:father, z: grandfather
if(z&&!isroot(y)){//judge whether it's a root
if(ch[z][0]==y)ch[z][0]=x;
else ch[z][1]=x;
//树旋转(tree spinning???
}
ch[y][k]=ch[x][!k]; fa[ch[x][!k]]=y;
ch[x][!k]=y; fa[y]=x;
fa[x]=z;
//reset father and son
push_up(y);
push_up(x);
//reset size
}
void splay(int rt)
{
int top=0,stack[MAXN];//use stack to store all the roots involved
stack[++top]=rt;//the first root
for(int i=rt;!isroot(i);i=fa[i])
stack[++top]=fa[i];//use function isroot()
while(top)pushdown(stack[top--]);//passing down tags
while(!isroot(rt)){
int x=fa[rt],y=fa[x];
if(!isroot(x)){
if((ch[x][0]==rt)^(ch[y][0]==x))turn(rt);
else turn(x);
//判断是一字型还是之字形进行different spinning
}
turn(rt);//for efficiency
}
push_up(rt);
}
void access(int x)
{
for(int y=0;x;y=x,x=fa[x])
{
splay(x);
ch[x][1]=y;
push_up(x);
}
}
void makeroot(int x)
{
access(x);
splay(x);
flag[x]^=1;
}
void split(int x, int y)
{
makeroot(x);
access(y);
splay(y);
}
void cut(int x, int y)
{
split(x,y);
fa[x]=0;
ch[y][0]=0;
push_up(y);
}
void link(int x, int y)
{
makeroot(x);
fa[x]=y;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n+1;++i)
sz[i]=1;
int a,b,c;
for(int i=1;i<=n;++i)
{
scanf("%d",&a);
g_v[i]=a;
if(i+a<=n)
link(i,i+a);
else
link(i,n+1);
}
scanf("%d",&m);
for(int i=1;i<=m;++i)
{
scanf("%d %d",&a,&b);
b++;
if(a==1)
{
makeroot(b);
access(n+1);
splay(n+1);
printf("%d\n",sz[n+1]-1);
}
else if(a==2)
{
scanf("%d",&c);
//if exceeds n, it means the sheep is bounced into the sky(hahaha
if(b+g_v[b]>n)
cut(b,n+1),g_v[b]=c;// reset the valueeeeee
else
cut(b,b+g_v[b]),g_v[b]=c;
if(b+c>n)//similar
link(b,n+1);
else
link(b,b+c);
}
}
return 0;
}
//good luck~