题目链接:传送门
指针版
建点建到
到了代表弹飞了
输入弹力系数的时候就直接维护每个节点的子树
操作打通j到
之间的重链,输出
的
,也就是深度
操作
掉原来的边再建新边,注意判断是不是连到
即可
由于它告诉你编号从~
,所以把编号全体上挪一位
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <complex>
#include <algorithm>
#include <climits>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define
#define
using namespace std;
typedef long long ll;
int tot, n, m, x, y, w[A];
namespace LCT {
struct node* null;
struct node {
node *ch[2], *fa;
int siz, rev;
bool whether() {
return fa->ch[1] == this;
}
bool isroot() {
return fa == null or (fa->ch[0] != this and fa->ch[1] != this);
}
void update() {
siz = 1;
if (ch[0] != null) siz += ch[0]->siz;
if (ch[1] != null) siz += ch[1]->siz;
}
void down() {
if (this == null or !rev) return;
swap(ch[0], ch[1]);
ch[0]->rev ^= 1;
ch[1]->rev ^= 1;
rev = 0;
}
void setnode(bool k, node *c) {
down();
ch[k] = c;
if (c != null) c->fa = this;
}
}pool[A];
#define
void init() {
null = pool;
null->ch[0] = null->ch[1] = null->fa = null;
null->siz = null->rev = 0;
}
ND newnode(int val) {
ND x = pool + ++tot;
x->ch[0] = x->ch[1] = x->fa = null;
x->siz = 1;
return x;
}
void rotate(ND x) {
node *fa = x->fa, *grand = fa->fa;
if (!fa->isroot()) grand->down();
fa->down(); x->down();
int dir = x->whether();
fa->setnode(dir, x->ch[dir ^ 1]);
if (fa->isroot()) x->fa = fa->fa;
else grand->setnode(fa->whether(), x);
x->setnode(dir ^ 1, fa);
fa->update(); x->update();
}
void fix(ND x) {
if (!x->isroot()) fix(x->fa);
x->down();
}
void splay(ND x) {
fix(x);
while (!x->isroot()) {
if (!x->fa->isroot())
x->whether() == x->fa->whether() ? rotate(x->fa) : rotate(x);
rotate(x);
}
x->update();
}
ND access(ND x) {
ND y = null;
while (x != null) {
splay(x);
x->ch[1] = y;
x->update();
y = x;
x = x->fa;
}
return y;
}
void makeroot(ND x) {
access(x)->rev = 1;
splay(x);
}
void link(ND x, ND y) {
makeroot(x);
x->fa = y;
}
void cut(ND x, ND y) {
makeroot(x);
access(y);
splay(x);
if (x->ch[1] == y and x->ch[1]->ch[0] != null) return;
x->ch[1] = y->fa = null;
}
int ask(int x, int y) {
ND a = pool + x;
ND b = pool + y;
makeroot(a);
access(b);
splay(b);
return b->siz;
}
}
int main(int argc, char const *argv[]) {
LCT::init();
scanf("%d", &n);
for (int i = 1; i <= n + 1; i++) LCT::newnode(1);
for (int i = 1; i <= n; i++) {
scanf("%d", &w[i]);
LCT::ND a = LCT::pool + i;
LCT::ND b = LCT::pool + i + w[i];
LCT::ND c = LCT::pool + n + 1;
if (i + w[i] <= n) LCT::link(a, b);
else LCT::link(a, c);
}
scanf("%d", &m);
while (m--) {
int opt;
scanf("%d", &opt);
if (opt == 1) {
scanf("%d", &x); x++;
printf("%d\n", LCT::ask(x, n + 1) - 1);
}
else {
scanf("%d%d", &x, &y); x++;
LCT::ND a = LCT::pool + x;
LCT::ND b = LCT::pool + x + w[x];
LCT::ND c = LCT::pool + n + 1;
LCT::ND d = LCT::pool + x + y;
LCT::cut(a, x + w[x] <= n ? b : c);
LCT::link(a, x + y <= n ? d : c);
w[x] = y;
}
}
}