[HNOI 2010] 彈飛綿羊
阿新 • • 發佈:2018-12-21
[題目連結]
https://www.lydsy.com/JudgeOnline/problem.php?id=2002
[演算法]
LCT動態維護森林連通性
時間複雜度 : O(NlogN ^ 2)
[程式碼]
#include<bits/stdc++.h> using namespace std; constint MAXN = 2e5 + 10; typedef long long ll; typedef long double ld; typedef unsigned long long ull; int n; int k[MAXN]; struct Link_Cut_Tree { struct Node { int father , son[2] , size; bool tag; } a[MAXN]; inline void init() {for (int i = 1; i <= n; i++) { a[i].father = 0; a[i].son[0] = a[i].son[1] = 0; a[i].size = 1; a[i].tag = false; } } inline void pushdown(int x) {if (a[x].tag) { swap(a[x].son[0] , a[x].son[1]); a[a[x].son[0]].tag ^= 1; a[a[x].son[1]].tag ^= 1; a[x].tag = false; } } inline void update(int x) { a[x].size = 1; if (a[x].son[0]) a[x].size += a[a[x].son[0]].size; if (a[x].son[1]) a[x].size += a[a[x].son[1]].size; } inline bool get(int x) { pushdown(a[x].father); return a[a[x].father].son[1] == x; } inline bool nroot(int x) { return a[a[x].father].son[0] == x | a[a[x].father].son[1] == x; } inline void rotate(int x) { int f = a[x].father , g = a[f].father; int tmpx = get(x) , tmpf = get(f); int w = a[x].son[tmpx ^ 1]; if (nroot(f)) a[g].son[tmpf] = x; a[x].son[tmpx ^ 1] = f; a[f].son[tmpx] = w; if (w) a[w].father = f; a[f].father = x; a[x].father = g; update(f); } inline void access(int x) { for (int y = 0; x; x = a[y = x].father) { splay(x); a[x].son[1] = y; update(x); } } inline void splay(int x) { int y = x , z = 0; static int st[MAXN]; st[++z] = y; while (nroot(y)) st[++z] = y = a[y].father; while (z) pushdown(st[z--]); while (nroot(x)) { int y = a[x].father , z = a[y].father; if (nroot(y)) rotate((a[y].son[0] == x) ^ (a[z].son[0] == y) ? x : y); rotate(x); } update(x); } inline void make_root(int x) { access(x); splay(x); a[x].tag ^= 1; pushdown(x); } inline int find_root(int x) { access(x); splay(x); while (a[x].son[0]) { pushdown(x); x = a[x].son[0]; } return x; } inline void link(int x , int y) { make_root(x); if (find_root(y) != x) a[x].father = y; } inline void cut(int x , int y) { make_root(x); if (find_root(y) == x && a[x].father == y && !a[x].son[1]) { a[x].father = a[y].son[0] = 0; update(y); } } inline int query(int u) { make_root(u); access(n + 1); splay(n + 1); return a[n + 1].size - 1; } inline void modify(int u , int val) { if (u + k[u] <= n) cut(u , u + k[u]); else cut(u , n + 1); if (u + val <= n) link(u , u + val); else link(u , n + 1); k[u] = val; } } LCT; template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); } template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); } template <typename T> inline void read(T &x) { T f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } int main() { read(n); LCT.init(); for (int i = 1; i <= n; i++) { read(k[i]); if (i + k[i] <= n) LCT.link(i , i + k[i]); else LCT.link(i , n + 1); } int m; read(m); while (m--) { int type; read(type); if (type == 1) { int x; read(x); ++x; printf("%d\n" , LCT.query(x)); } else { int x , val; read(x); read(val); ++x; LCT.modify(x , val); } } return 0; }