一棵有根树,支持两种操作:
1,查询指定节点深度
2,为指定节点换父亲
既然树形态改变了,那么就把一切都交给LCT吧。。
LCT的关键函数access()只有10行,但是加上了splay,调起来还是作死的节奏啊,吐血2天终于AC了
关于link-cut tree的复杂度,虽然不会证,但我能造出的极限数据是n个节点的完美二叉树,然后相邻两个询问是两个路径尽量不相同的叶子节点,使splay的功效降到最低,每次都要从叶子一步一步走到根,单次logn,那么就是nlogn的复杂度了。但是对于splay本身巨大的常数只能说一声:呵呵
这里的splay只是作为载体而存在,所以简化了一些操作过程,也因此失去了形如o->ch[1]->ch[0]这样提取区间的功能,但还是能够很方便的做到提取一段链
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <time.h>
using namespace std;
const int N = 202000;
int n;
struct Node *nill;
struct Node {
Node *ch[2],*fa;
int sz;
bool d() { return fa->ch[1]==this; }
bool is() { return fa==nill || fa->ch[0]!=this && fa->ch[1]!=this; }
void setc(Node *o,int c) {
ch[c] = o;
o->fa = this;
up();
}
void up() {
if (this==nill) return ;
sz = ch[0]->sz + ch[1]->sz + 1;
}
void rot() {
int c = d();
Node *tmp = fa;
tmp->setc(ch[c^1],c);
if (tmp->is()) fa = tmp->fa;
else tmp->fa->setc(this,tmp->d());
setc(tmp,c^1);
fa->up();
}
void splay() {
while (!is()) {
if (!fa->is()) {
d()==fa->d() ? fa->rot() : rot();
}
rot();
}
}
void access() {
Node *p = this,*q = nill;
while (p!=nill) {
p->splay();
p->setc(q,1);
q = p;
p = p->fa;
}
splay();
}
}memo[N],*idx[N],*bat;
void change(Node *a,Node *b) {
a->splay();
a->ch[0]->fa = a->fa;
a->setc(nill,0);
a->fa = b;
}
void newNode(Node *&o) {
o = bat ++;
o->ch[0] = o->ch[1] = o->fa = nill;
o->sz =1;
}
void init() {
bat = memo;
newNode(nill); nill->sz = 0;
}
void show(Node *o) {
if (o==nill) return ;
show(o->ch[0]);
printf("%d ",o-memo);
show(o->ch[1]);
}
inline void read(int &x) {
char c; bool sig = 0;
for (c = getchar(); c<'0' || c>'9'; c = getchar()) if (c=='-') sig = 1;
for (x = c-'0',c = getchar(); c>='0' && c<='9'; c = getchar()) x = x*10+c-'0';
sig && (x=-x);
}
int main() {
// freopen("in.txt","r",stdin);
while (scanf("%d",&n)==1) {
init();
for (int i = 0; i <= n; i ++) {
newNode(idx[i]);
}
for (int i = 0; i < n; i ++) {
int x;
read(x);
idx[i]->fa = idx[min(n,i+x)];
}
int nq;
read(nq);
while (nq--) {
int op,a,b;
read(op); read(a);
if (op==1) {
idx[a]->access();
printf("%d\n",idx[a]->sz - 1);
} else {
read(b);
b = min(n,a+b);
change(idx[a],idx[b]);
}
}
}
// printf("%.6f\n",(double)clock()/CLOCKS_PER_SEC);
return 0;
}