洛谷 P3203 [HNOI2010]彈飛綿羊
阿新 • • 發佈:2018-12-24
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]彈飛綿羊