【BZOJ2002】【HNOI2010】Bounce 弹飞绵羊

【题目链接】

【思路要点】

  • 补档博客,无题解。

【代码】

#include<bits/stdc++.h>
using namespace std;
#define MAXN	200005
int n;
struct LinkCutTree {
	struct Node {
		bool rev;
		int father, child[2], size, up;
	};
	Node a[MAXN];
	int n;
	void init(int x) {
		n = x;
		for (int i = 1; i <= n; i++) {
			a[i].rev = false;
			a[i].father = 0;
			a[i].child[0] = 0;
			a[i].child[1] = 0;
			a[i].size = 1;
			a[i].up = 0;
		}
	}
	void pushdown(int x) {
		if (a[x].rev == false) return;
		swap(a[x].child[0], a[x].child[1]);
		a[a[x].child[0]].rev ^= true;
		a[a[x].child[1]].rev ^= true;
		a[x].rev = false;
	}
	bool get(int x) {
		pushdown(a[x].father);
		return x == a[a[x].father].child[1];
	}
	void update(int x) {
		a[x].size = 1;
		a[x].size += a[a[x].child[0]].size;
		a[x].size += a[a[x].child[1]].size;
	}
	void rotate(int x) {
		int f = a[x].father, g = a[f].father;
		pushdown(f); pushdown(x);
		int tmp = get(x);
		a[x].up = a[f].up;
		a[f].up = 0;
		a[f].child[tmp] = a[x].child[tmp ^ 1];
		a[a[x].child[tmp ^ 1]].father = f;
		a[x].child[tmp ^ 1] = f;
		a[f].father = x;
		a[x].father = g;
		a[g].child[a[g].child[1] == f] = x;
		update(f); update(x);
	}
	void splay(int x) {
		pushdown(x);
		for (int f = a[x].father; (f = a[x].father); rotate(x))
			if (a[f].father) rotate((get(f) == get(x)) ? f : x);
	}
	void access(int x) {
		splay(x);
		a[a[x].child[1]].father = 0;
		a[a[x].child[1]].up = x;
		a[x].child[1] = 0;
		update(x);
		while (a[x].up) {
			int tmp = a[x].up;
			splay(tmp);
			a[a[tmp].child[1]].father = 0;
			a[a[tmp].child[1]].up = tmp;
			a[tmp].child[1] = x;
			a[x].father = tmp;
			a[x].up = 0;
			update(tmp);
			x = tmp;
		}
	}
	void reverse(int x) {
		access(x);
		splay(x);
		a[x].rev ^= true;
	}
	void link(int x, int y) {
		access(x);
		splay(x);
		reverse(y);
		a[x].child[1] = y;
		a[y].father = x;
		update(x);
	}
	void cut(int x, int y) {
		reverse(x);
		access(y);
		splay(x);
		a[x].child[1] = 0;
		a[y].father = 0;
		update(x);
	}
	int query(int x) {
		reverse(n);
		access(x);
		splay(x);
		return a[x].size;
	}
};
LinkCutTree T;
int value[MAXN];
int main() {
	scanf("%d", &n);
	T.init(n + 1);
	for (int i = 1; i <= n; i++) {
		scanf("%d", &value[i]);
		if (i + value[i] <= n) T.link(i, i + value[i]);
		else T.link(i, n + 1);
	}
	int q;
	scanf("%d", &q);
	for (int i = 1; i <= q; i++) {
		int opt, x;
		scanf("%d%d", &opt, &x);
		x++;
		if (opt == 1) printf("%d\n", T.query(x) - 1);
		else {
			if (x + value[x] <= n) T.cut(x, x + value[x]);
			else T.cut(x, n + 1);
			scanf("%d", &value[x]);
			if (x + value[x] <= n) T.link(x, x + value[x]);
			else T.link(x, n + 1);
		}
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值