Lct裸题
给出一棵树,有修改及询问,修改操作为修改一个节点的父亲,询问一个节点到根的点数。
询问及修改前只需Access一遍即可。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#define Rep(i, x, y) for (int i = x; i <= y; i ++)
#define RepE(i, x) for (int i = pos[x]; i; i = g[i].nex)
#define lc t[x].ch[0]
#define rc t[x].ch[1]
#define Lc t[lc]
#define Rc t[rc]
#define tp t[x].par
#define Tp t[t[x].par]
using namespace std;
typedef long long LL;
const int N = 200005;
struct arr { int ch[2], par, sz; } t[N];
bool rt[N];
int n, m, q;
void Upd(int x) { t[x].sz = Lc.sz + Rc.sz + 1; }
void Sc(int x, int y, bool f) { t[y].ch[f] = x, tp = y; }
void Rot(int x, bool f) {
int y = tp;
Sc(t[x].ch[f], y, !f);
tp = Tp.par; Sc(y, x, f);
if (rt[y]) rt[y] = 0, rt[x] = 1;
else Tp.ch[Tp.ch[1] == y] = x;
Upd(y);
}
void Splay(int x) {
while (!rt[x]) {
if (rt[tp]) { Rot(x, Tp.ch[0] == x); break; }
bool f = (t[Tp.par].ch[1] == tp);
if (Tp.ch[f] == x) Rot(tp, !f), Rot(x, !f);
else Rot(x, f), Rot(x, !f);
} Upd(x);
}
void Access(int x) {
Splay(x);
rt[rc] = 1, rc = 0;
while (tp) { //cout << 1;
int y = tp;
Splay(y);
rt[t[y].ch[1]] = 1;
t[y].ch[1] = x;
rt[x] = 0;
x = tp, Upd(x);
}
}
int main()
{
cin >> n;
Rep(i, 1, n) {
int x;
scanf ("%d", &x), x = min(x+i, n+1);
t[i].par = x, rt[i] = 1, t[x].sz = 1;
}
rt[n+1] = 1, t[n+1].sz = 1;
cin >> q;
Rep(i, 1, q) {
int type, x;
scanf ("%d%d", &type, &x), x ++;
if (type == 1) {
Access(x); Splay(x);
printf ("%d\n", t[x].sz - 1);
} else {
int y;
scanf ("%d", &y), y = min(x+y, n+1);
Access(x); Splay(x);
rt[lc] = 1, Lc.par = tp, lc = 0;
t[x].sz = Rc.sz + 1, tp = y;
}
}
return 0;
}