BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊

Description

某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏。游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹ki步,达到第i+ki个装置,若不存在第i+ki个装置,则绵羊被弹飞。绵羊想知道当它从第i个装置起步时,被弹几次后会被弹飞。为了使得游戏更有趣,Lostmonkey可以修改某个弹力装置的弹力系数,任何时候弹力系数均为正整数。

Input

第一行包含一个整数n,表示地上有n个装置,装置的编号从0到n-1,接下来一行有n个正整数,依次为那n个装置的初始弹力系数。第三行有一个正整数m,接下来m行每行至少有两个数i、j,若i=1,你要输出从j出发被弹几次后被弹飞,若i=2则还会再输入一个正整数k,表示第j个弹力装置的系数被修改成k。对于20%的数据n,m<=10000,对于100%的数据n<=200000,m<=100000

Output

对于每个i=1的情况,你都要输出一个需要的步数,占一行。

Sample Input

4

1 2 1 1

3

1 1

2 1 1

1 1

Sample Output

2

3

Solution

大神题解Orz…

大致思路应该是用size维护深度,因为我们搞出来一条链,size大小就是深度大小吧。

Code

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
#include <iostream>
#include <cstdio>
using namespace std;
const int INF = 1<<30;
typedef long long LL;
int getint() {
	int r = 0, k = 1; char c = getchar();
	for (; '0' > c || c > '9'; c = getchar()) if (c == '-') k = -1;
	for (; '0' <= c && c <= '9'; c = getchar()) r = r * 10 - '0' + c;
	return r * k;
}
char getop() {
	char c = getchar();
	for (; 'A' > c || c > 'Z'; c = getchar());
	return c;
}
int n, m;
int fa[10005] , c[10005][2], st[10005], size[10005], rev[10005];
int b[10005];
bool isroot(int x) { return c[fa[x]][0]!=x&&c[fa[x]][1]!=x; }
void pushup(int x) {
	size[x] = size[c[x][0]] + size[c[x][1]] + 1;
}
void pushdown(int x) {
	if (rev[x]) {
		rev[x] = 0; rev[c[x][0]] ^= 1; rev[c[x][1]] ^= 1;
		swap(c[x][0], c[x][1]);
	}
}
int wson(int x) {
	return c[fa[x]][1] == x;
}
void rotate(int x) {
	int y = fa[x], z = fa[y], a = wson(x), b = !a;
    if (!isroot(y)) {
    	if (y == c[z][0]) c[z][0] = x;
    	else c[z][1] = x;
    }
    fa[x] = z; fa[y] = x; fa[c[x][b]] = y;
    c[y][a] = c[x][b]; c[x][b] = y;
    pushup(y); pushup(x);
}
void splay(int x) {
	int tail = 1; st[1] = x;
	for (int i = x; !isroot(i); i = fa[i])
		st[++tail] = fa[i];
	for (int i = tail; i; i --) pushdown(st[i]);
	while (!isroot(x)) {
		int y = fa[x], z = fa[y], a = wson(x), b = wson(y);
		if (!isroot(y)) {
			if (a == b) rotate(y);
			else rotate(x);
		}
		rotate(x);
	}
}
void access(int x) {
	int y = 0;
	while (x) {
		splay(x);
		c[x][1] = y;
		y = x; x = fa[x];
	}
}
void rever(int x) {
	access(x); splay(x); rev[x] ^= 1;
}
void link(int x, int y) {
	rever(x);
	fa[x] = y;
	splay(x);
}
void cut(int x, int y) {
	rever(x);
	access(y);
	splay(y);
	fa[x] = 0;
	c[y][0] = 0;
}
int main() {
	n = getint();
	int x;
	for (int i = 1; i <= n; ++i) {
		x = getint();
		size[i] = 1;
		if (i + x > n+1) b[i] = n+1;
		else b[i] = i+x;
		fa[i] = b[i];
	}
	int m;
	m = getint();
	size[n+1] = 1;
	int op, y;
	while (m--) {
		op = getint();
		if (op == 1) {
			rever(n+1);
			x = getint();x++;
			access(x);
			splay(x);
			printf("%d\n", size[c[x][0]]);
		} else {
			x = getint(); y = getint();x++;
			cut(x, b[x]);
			if (x + y > n+1) b[x] = n+1;
			else b[x] = x+y;
			link(x, b[x]);
		}
	}
	return 0;	
}