洛谷 P3203 [HNOI2010]弹飞绵羊

题解

题目中编号从 0 开始,方便起见,代码中加上 1 使得从 1 开始。

首先从 (i) 弹射 (k) 就是指 (i)(i + k) 连边,对于 目标 (gt n) 的全部指向 (n + 1)。询问 (i) 时直接 (access(i, n + 1)),输出这个 Splay 的 (size) 即可。

代码

#include<bits/stdc++.h>

using namespace std;

const int maxn = 200000 + 5;

int n, m;

namespace LCT
{
    // PartI. Splay
    int fa[maxn], ch[2][maxn], size[maxn], st[maxn], sz; bool flip[maxn];
    bool inline notroot(int o) {
        return (ch[0][fa[o]] == o) || (ch[1][fa[o]] == o);
    }
    void inline pushdown(int o) {
        if(flip[o]) {
            if(ch[0][o]) flip[ch[0][o]] ^= 1;
            if(ch[1][o]) flip[ch[1][o]] ^= 1;
            swap(ch[0][o], ch[1][o]);
            flip[o] = false;
        }
    }
    void inline pushup(int o) {
        size[o] = size[ch[0][o]] + size[ch[1][o]] + 1;
    }
    void inline rotate(int x) {
        int y = fa[x], z = fa[y], d = ch[1][y] == x;
        if(notroot(y)) ch[y == ch[1][z]][z] = x; fa[x] = z;
        ch[d][y] = ch[d^1][x]; if(ch[d][y]) fa[ch[d][y]] = y; ch[d^1][x] = y; fa[y] = x;
        pushup(y); pushup(x);
    }
    void inline splay(int x) {
//		printf("In splay
");
        int o = x;
        st[sz = 1] = o;
        while(notroot(o)) st[++sz] = o = fa[o];
//		printf("stack!
");
        while(sz) pushdown(st[sz--]);
        while(notroot(x)) {
            int y = fa[x], z = fa[y];
//			printf("y = %d, z = %d
", y, z);
            if(notroot(y)) rotate(((ch[0][z] == y) ^ (ch[0][y] == x)) ? x : y);
            rotate(x);
        }
        pushup(x);
    }
    // debug
    void inline debug() {
        for(int i = 1; i <= n + 1; ++i) {
            printf("%d:"%d"<%d>(%d)[%d, %d]
", i, flip[i], size[i], fa[i], ch[0][i], ch[1][i]);
        }
    }
    // PartII. LCT
    void inline access(int x) {
        for(int y = 0; x; y = x, x = fa[x]) {
            splay(x);
            ch[1][x] = y;
            pushup(x);
        }
    }
    void inline makeroot(int x) {
//		printf("In makeroot.
");
        access(x); 
//		printf("access ok.
");
//		debug();
        splay(x);
        flip[x] ^= 1;
    }
    void inline split(int x, int y) {
        makeroot(x);
//		printf("makeroot ok.
");
//		debug();
        access(y); splay(y);
    }
    void inline link(int x, int y) {
        makeroot(x);
        fa[x] = y;
    }
    void inline cut(int x, int y) {
        split(x, y);
        fa[x] = ch[0][y] = 0;
        pushup(y);
    }
}

int opt, i, k;
int lk[maxn];
void inline Init()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i) {
        scanf("%d", &k);
        lk[i] = LCT::fa[i] = (i + k > n) ? n + 1 : i + k;
    }
    scanf("%d", &m);
}

void inline Solve()
{
    while(m--) {
//		LCT::debug();
        scanf("%d %d", &opt, &i);
        ++i;
        if(opt == 1) {
            LCT::split(i, n + 1);
            printf("%d
", LCT::size[n + 1] - 1);
        } else {
            scanf("%d", &k);
            LCT::cut(i, lk[i]);
            LCT::link(i, lk[i] = (i + k > n) ? n + 1 : i + k);
        }
//		printf("ok.
");
    }
}

int main()
{
    Init();
    Solve();
    return 0;
}
原文地址:https://www.cnblogs.com/cjrsacred/p/10167953.html