【bzoj2002】[Hnoi2010]Bounce 弹飞绵羊
题目描述:
某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏。游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹ki步,达到第i+ki个装置,若不存在第i+ki个装置,则绵羊被弹飞。绵羊想知道当它从第i个装置起步时,被弹几次后会被弹飞。为了使得游戏更有趣,Lostmonkey可以修改某个弹力装置的弹力系数,任何时候弹力系数均为正整数。
输入:
第一行包含一个整数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
输出:
对于每个i=1的情况,你都要输出一个需要的步数,占一行。
样例输入:
4
1 2 1 1
3
1 1
2 1 1
1 1
样例输出:
2
3
题解:
把每个位置看成一个点,每个点往后跳的位置看做是树的边,新建一个点表示被弹飞的点(根节点)。你需要支持修改边,查询某个点的深度。lct果题。(第一次写lct)
代码:
#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #ifdef WIN32 #define LL "%I64d" #else #define LL "%lld" #endif #ifdef CT #define debug(...) printf(__VA_ARGS__) #define setfile() #else #define debug(...) #define filename "" #define setfile() freopen(filename".in", "r", stdin); freopen(filename".out", "w", stdout); #endif #define R register #define getc() (S == T && (T = (S = B) + fread(B, 1, 1 << 15, stdin), S == T) ? EOF : *S++) #define dmax(_a, _b) ((_a) > (_b) ? (_a) : (_b)) #define dmin(_a, _b) ((_a) < (_b) ? (_a) : (_b)) #define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0) #define cmin(_a, _b) (_a > (_b) ? _a = (_b) : 0) char B[1 << 15], *S = B, *T = B; inline int FastIn() { R char ch; R int cnt = 0; R bool minus = 0; while (ch = getc(), (ch < '0' || ch > '9') && ch != '-') ; ch == '-' ? minus = 1 : cnt = ch - '0'; while (ch = getc(), ch >= '0' && ch <= '9') cnt = cnt * 10 + ch - '0'; return minus ? -cnt : cnt; } #define maxn 200010 struct Node *null; struct Node { Node *ch[2], *fa; int size; inline void update() { size = ch[0] -> size + ch[1] -> size + 1; } inline bool type() { return fa -> ch[1] == this; } inline bool check() { return fa -> ch[type()] == this; } inline void rotate() { R Node *f = fa; R bool d = type(); (fa = f -> fa), f -> check() ? fa -> ch[f -> type()] = this : 0; (f -> ch[d] = ch[!d]) != null ? ch[!d] -> fa = f : 0; f -> fa = this; ch[!d] = f; f -> update(); } inline void splay() { for (; check(); rotate()) if (fa -> check()) (type() != fa -> type() ? this : fa) -> rotate(); update(); } inline Node *access() { R Node *i = this, *j = null; for (; i != null; i = (j = i) -> fa) { i -> splay(); i -> ch[1] = j; i -> update(); } return j; } inline void make_root() { access(); splay(); } inline void link(R Node *that) { make_root(); ch[0] -> fa = null; ch[0] = null; fa = that; update(); } }mem[maxn], *tot = mem, *fir = mem; int main() { // setfile(); null = mem; null -> size = 0; null -> fa = null -> ch[0] = null -> ch[1] = null; R int n = FastIn(); for (R int i = 1; i <= n; ++i) *++tot = (Node) {null, null, null, 1}; for (R int i = 1; i <= n; ++i) { R int x = FastIn(); if (i + x <= n) (mem + i) -> fa = mem + i + x; } R int m = FastIn(); for (R int i = 1; i <= m; ++i) { R int opt = FastIn(), x = FastIn() + 1; if (opt == 1) { R Node *now = fir + x; now -> make_root(); printf("%d\n",now -> size ); } else { R int k = FastIn(); R Node *now = fir + x; now -> link(x + k > n ? null : now + k); } } return 0; } /* 4 1 2 1 1 3 1 1 2 1 1 1 1 */