1. 程式人生 > >洛谷 P3203 [HNOI2010]彈飛綿羊

洛谷 P3203 [HNOI2010]彈飛綿羊

spl names rotate c++ bit ces inline not sca

題解

題目中編號從 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\n");
        int o = x;
        st[sz = 1] = o;
        while(notroot(o)) st[++sz] = o = fa[o];
//      printf("stack!\n");
        while(sz) pushdown(st[sz--]);
        while(notroot(x)) {
            int y = fa[x], z = fa[y];
//          printf("y = %d, z = %d\n", 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]\n", 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.\n");
        access(x); 
//      printf("access ok.\n");
//      debug();
        splay(x);
        flip[x] ^= 1;
    }
    void inline split(int x, int y) {
        makeroot(x);
//      printf("makeroot ok.\n");
//      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\n", 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.\n");
    }
}

int main()
{
    Init();
    Solve();
    return 0;
}

洛谷 P3203 [HNOI2010]彈飛綿羊