# BZOJ-2008 弹飞绵羊(LCT)

## 2002: [Hnoi2010]Bounce 弹飞绵羊

Time Limit: 10 Sec  Memory Limit: 259 MB
Submit: 11350  Solved: 5769
[Submit][Status][Discuss]

4
1 2 1 1
3
1 1
2 1 1
1 1

## Sample Output

2
3

LCT模板题，把n+1当做公共父节点，每次求左子树大小即可

`#include<cstdio>#include<string.h>#include<queue>#include<algorithm>using namespace std;const int MX = 2e5 + 5;const int inf = 0x3f3f3f3f;int n, m;struct LCT {    int fa[MX], ch[MX][2], rev[MX], sz[MX];    void init() {        for (int i = 0; i <= n + 1; i++) {            ch[i][0] = ch[i][1] = rev[i] = fa[i] = 0;            sz[i] = 1;        }        sz[0] = 0;    }    inline bool check_root(int x) {        return ch[fa[x]][0] != x && ch[fa[x]][1] != x;    }    inline int check_same(int x) {        return x == ch[fa[x]][1];    }    inline void up_rev(int x) {        rev[x] ^= 1;        swap(ch[x][0], ch[x][1]);    }    void pushup(int x) {        sz[x] = sz[ch[x][0]] + sz[ch[x][1]] + 1;    }    void pushdown(int x) {        if (rev[x]) {            if (ch[x][0]) up_rev(ch[x][0]);            if (ch[x][1]) up_rev(ch[x][1]);            rev[x] = 0;        }    }    void P(int x) {        if (!check_root(x)) P(fa[x]);        pushdown(x);    }    void rotate(int x) {        int y = fa[x], z = fa[y], kind = ch[y][1] == x;        if (!check_root(y)) ch[z][ch[z][1] == y] = x;        fa[x] = z; fa[y] = x; fa[ch[x][!kind]] = y;        ch[y][kind] = ch[x][!kind]; ch[x][!kind] = y;        pushup(y);    }    void splay(int x) {        P(x);        int y, z;        while (!check_root(x)) {            y = fa[x]; z = fa[y];            if (!check_root(y)) {                if (check_same(x) == check_same(y)) rotate(y);                else rotate(x);            }            rotate(x);        }        pushup(x);    }    void access(int x) {        int y = 0;        while (x) {            splay(x);            ch[x][1] = y;            pushup(x);            x = fa[y = x];        }    }    void make_root(int x) {  //将x作为根节点        access(x); splay(x); up_rev(x);    }    void link(int x, int y) {        make_root(x); fa[x] = y; access(x);    }    void cut(int x, int y) {        make_root(x); access(y); splay(y);        ch[y][0] = fa[x] = 0;    }    int find(int x) {  //找根节点        access(x); splay(x);        while (ch[x][0]) x = ch[x][0];        return x;    }    void print(int x) {        if (ch[x][0])print(ch[x][0]);        printf("[%d]", x);        if (ch[x][1])print(ch[x][1]);    }    int query(int x) {        make_root(n + 1);        access(x);        splay(x);        //print(x);printf("\n");        return sz[ch[x][0]];    }} T;int a[MX];int main() {    freopen("in.txt", "r", stdin);    while (~scanf("%d", &n)) {        for (int i = 1; i <= n; i++) scanf("%d", &a[i]);        T.init();        for (int i = 1; i <= n; i++) {            a[i] = min(n + 1, a[i] + i);            T.link(i, a[i]);        }        scanf("%d", &m);        for (int i = 1, op, u, k; i <= m; i++) {            scanf("%d%d", &op, &u); u++;            if (op == 1) printf("%d\n", T.query(u));            else {                scanf("%d", &k);                T.cut(u, a[u]);                T.link(u, a[u] = min(n + 1, u + k));            }        }    }    return 0;}`

0 0