题目大意
要求维护一棵有根树,支持断开一条边并加入一条边,查询到根的距离。
题解
LCT维护即可,注意是有根树,link和cut之前不能move_root否则会tle。
代码
#include <cstdio>
#include <iostream>
using namespace std;
const int maxn=
int(
2e5)+
111;
int n,m;
int p[maxn];
struct Node {
int key,siz;
Node *ch[
2],*fa;
Node();
Node(
int);
int son() {
if(
this==fa->ch[
0])
return 0;
if(
this==fa->ch[
1])
return 1;
return -
1;
}
void maintain();
}*
null,node[maxn];
Node:: Node():key(-
1) {
siz=
null?
1:
0;
ch[
0]=ch[
1]=fa=
null;
}
Node:: Node(
int _):key(_) {
siz=
null?
1:
0;
ch[
0]=ch[
1]=fa=
null;
}
void Node:: maintain() {
siz=ch[
0]->siz+
1+ch[
1]->siz;
return;
}
void Rotate(Node* cur,
int dir) {
Node* tmp=cur->ch[dir^
1];
cur->ch[dir^
1]=tmp->ch[dir], tmp->ch[dir]->fa=cur;
tmp->ch[dir]=cur;
cur->maintain(), tmp->maintain();
if(~cur->son()) cur->fa->ch[cur->son()]=tmp;
tmp->fa=cur->fa, cur->fa=tmp;
return;
}
void Splay(Node* cur) {
while(~cur->son()) {
int dir=cur->son();
if(dir==cur->fa->son()) Rotate(cur->fa->fa,dir^
1);
Rotate(cur->fa,dir^
1);
}
return;
}
void Access(Node* cur) {
Node* tmp=
null;
while(cur!=
null) {
Splay(cur);
cur->ch[
1]=tmp, cur->maintain();
tmp=cur, cur=cur->fa;
}
return;
}
void Modify(Node* x,Node* y) {
Access(x), Splay(x);
x->ch[
0]->fa=
null;
x->ch[
0]=
null, x->maintain();
x->fa=y;
return;
}
void init_null() {
null=
new Node(-
1);
null->ch[
0]=
null->ch[
1]=
null->fa=
null;
return;
}
int main() {
#ifndef ONLINE_JUDGE
freopen(
"input.txt",
"r",stdin);
freopen(
"output.txt",
"w",stdout);
#endif // ONLINE_JUDGE
init_null();
scanf(
"%d",&n);
for(
int i=
1;i<=n;i++) {
scanf(
"%d",&p[i]);
node[i]=Node(i);
if(i+p[i]<=n) node[i].fa=&node[i+p[i]];
}
scanf(
"%d",&m);
for(
int i=
0;i<m;i++) {
int op,x,y;
scanf(
"%d%d",&op,&x); x++;
if(op==
1) {
Access(&node[x]); Splay(&node[x]);
printf(
"%d\n",node[x].siz);
}
else {
scanf(
"%d",&y);
if(x+y<=n) Modify(&node[x],&node[x+y]);
else Modify(&node[x],
null);
}
}
return 0;
}
转载请注明原文地址: https://ju.6miu.com/read-671217.html