洛谷3203 弹飞绵羊(LCT)
Splay不rotate简直该打
【题目分析】
首先%一下黄学长。。。。。woc分块原来也能做。。。。大家可以拜读一下:传送门
好的现在说说我的做法,也就是网上一般的做法:LCT。
题意还是很简单,维护LCT,支持Link和Cut操作。
然后就没有然后了。。。。。。。
【代码~】
#include<bits/stdc++.h>
using namespace std;
const int MAXN=2e5+10;
int n,m;
int end[MAXN],fa[MAXN],ch[MAXN][2],siz[MAXN];
int val[MAXN],laz[MAXN];
int q[MAXN],last;
bool which(int x)
{
return x==ch[fa[x]][1];
}
void push_up(int root)
{
siz[root]=siz[ch[root][0]]+siz[ch[root][1]]+(root!=n+1);
}
int isroot(int x)
{
if(!fa[x])
return 1;
return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;
}
void push_down(int root)
{
if(laz[root])
{
swap(ch[root][0],ch[root][1]);
if(ch[root][0])
laz[ch[root][0]]^=1;
if(ch[root][1])
laz[ch[root][1]]^=1;
laz[root]=0;
}
}
void rotate(int x)
{
int y=fa[x],z=fa[y],a=which(x),b=which(y);
if(z&&!isroot(y))
ch[z][b]=x;
fa[y]=x,fa[x]=z;
ch[y][a]=ch[x][a^1];
ch[x][a^1]=y;
if(ch[y][a])
fa[ch[y][a]]=y;
push_up(y);
push_up(x);
}
void splay(int x)
{
q[last=0]=x;
for(int i=x;!isroot(i);i=fa[i])
q[++last]=fa[i];
for(int i=last;i>=0;--i)
push_down(q[i]);
while(!isroot(x))
{
if(!isroot(fa[x]))
{
if(which(x)==which(fa[x]))
rotate(fa[x]);
else
rotate(x);
}
rotate(x);
}
}
void access(int x)
{
for(int i=0;x;i=x,x=fa[x])
{
splay(x);
ch[x][1]=i;
push_up(x);
}
}
void makeroot(int x)
{
access(x);
splay(x);
laz[x]^=1;
push_down(x);
}
void link(int x,int y)
{
makeroot(x);
fa[x]=y;
}
void cut(int x,int y)
{
makeroot(x);
access(y);
splay(y);
fa[x]=0,ch[y][0]=0;
push_up(y);
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n+1;++i)
siz[i]=1;
for(int i=1;i<=n;++i)
{
int k;
scanf("%d",&k);
end[i]=k;
fa[i]=min(i+k,n+1);
}
scanf("%d",&m);
for(int i=1;i<=m;++i)
{
int cz,x;
scanf("%d%d",&cz,&x);
x++;
if(cz==1)
{
makeroot(n+1);
access(x);
splay(x);
printf("%d\n",siz[x]);
}
else
{
int y;
scanf("%d",&y);
cut(x,min(x+end[x],n+1));
link(x,min(x+y,n+1));
end[x]=y;
}
}
return 0;
}