【HNOI2010】弹飞绵羊的解析——LCT的复习

版权声明:转载请注明原出处啦(虽然应该也没人转载): https://blog.csdn.net/hzk_cpp/article/details/82926546

两个月没有写LCT了,这次写一遍复习一下.

题目:bzoj2002.

题目大意:给定一棵树,支持两种操作:

1.格式1 j,表示查询j的深度.

2.格式2 j k,表示修改j的父亲为j+k.

这道题是一个十分容易的LCT套路题(然而我还是看了好久题解才懂).

这棵树虽然是个有根树,要求一个节点的深度,就是求它到根的距离+1.

所以我们发现,我们可以建一个虚点n+1作为所有树的根.接下来我们把虚点移到根的地方,求一个点到这个根的距离.

这时候我们把这个点access一下,然后发现它现在是深度最大的点,且它到这个虚点的这条链被独立了出来,此时这条链的大小-1就是距离.

代码如下:

#include<bits/stdc++.h>
  using namespace std;
#define Abigail inline void
typedef long long LL;
const int N=200000;
int n,m,tmp[N+9],ttmp,nxt[N+9];
struct tree{
  int size,rev,s[2],fa;
}tr[N+9];
bool isroot(int x){
  return tr[tr[x].fa].s[0]^x&&tr[tr[x].fa].s[1]^x;
}
void pushup(int x){
  tr[x].size=tr[tr[x].s[0]].size+tr[tr[x].s[1]].size+1;
}
void update_rev(int x){
  tr[x].rev^=1;
  swap(tr[x].s[0],tr[x].s[1]);
} 
void pushdown(int x){
  if (!tr[x].rev) return;
  tr[x].rev=0;
  update_rev(tr[x].s[0]);update_rev(tr[x].s[1]);
}
void rtt(int x){
  int y=tr[x].fa,z=tr[y].fa,k=tr[y].s[1]==x;
  if (!isroot(y)) tr[z].s[tr[z].s[1]==y]=x;tr[x].fa=z;
  tr[y].s[k]=tr[x].s[k^1];if (tr[x].s[k^1]) tr[tr[x].s[k^1]].fa=y;
  tr[x].s[k^1]=y;tr[y].fa=x;
  pushup(y);pushup(x);
}
void splay(int x){
  int y,z;
  tmp[ttmp=1]=x;
  for (int i=x;!isroot(i);i=tr[i].fa) tmp[++ttmp]=tr[i].fa;
  for (;ttmp;ttmp--) pushdown(tmp[ttmp]);
  while (!isroot(x)){
    y=tr[x].fa,z=tr[y].fa;
    if (!isroot(y)) tr[y].s[1]==x^tr[z].s[1]==y?rtt(x):rtt(y);
    rtt(x);
  }
  pushup(x);
}
void access(int x){
  for (int t=0;x;t=x,x=tr[x].fa){
    splay(x);
    tr[x].s[1]=t;
    pushup(x);
  }
}
void makeroot(int x){
  access(x);splay(x);
  update_rev(x);
}
int root(int x){
  access(x);splay(x);
  while (tr[x].s[0]) x=tr[x].s[0];
  return x;
}
void split(int x,int y){
  makeroot(x);
  access(y);splay(y);
}
void link(int x,int y){
  if (root(x)==root(y)) return;
  makeroot(x);
  tr[x].fa=y;
}
void cut(int x,int y){
  if (root(x)^root(y)) return;
  split(x,y);
  if (tr[y].s[0]^x||tr[x].s[1]||tr[y].s[1]) return;
  tr[x].fa=tr[y].s[0]=0;
}
int query(int x){
  split(x,n+1);
  return tr[n+1].size-1;
}
Abigail into(){
  scanf("%d",&n);
  int y;
  for (int i=1;i<=n;i++){
    scanf("%d",&y);
    tr[i].size=1;
    if (i+y>n) link(i,n+1),nxt[i]=n+1;
    else link(i,i+y),nxt[i]=i+y;
  }
  tr[n+1].size=1;
}
Abigail work(){
}
Abigail outo(){
}
Abigail getans(){
  int opt,x,y,m;
  scanf("%d",&m);
  for (int i=1;i<=m;i++){
    scanf("%d",&opt);
    if (opt==1){
      scanf("%d",&x);++x;
      printf("%d\n",query(x));
    }else{
      scanf("%d%d",&x,&y);++x;
      cut(x,nxt[x]);
      if (x+y>n) link(x,n+1),nxt[x]=n+1;
      else link(x,x+y),nxt[x]=x+y;
    }
  }
}
int main(){
  into();
  work();
  outo();
  getans();
  return 0;
}

猜你喜欢

转载自blog.csdn.net/hzk_cpp/article/details/82926546