1、题目大意:就是给一个动态的森林求size域
2、分析: 这个就是一个动态树问题,对于每一个位置i有i+ki这个父亲, 于是这就是一个森林了,然后对于每一个修改直接lct维护就好,询问就是i到最外面的点的个数,恰好是一个链,就求一个
size就好
#include <stack> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> using namespace std; #define LL long long #define eps 1e-7 int n, m; struct Node{ Node *ch[2], *fa; bool rev; int size; inline int which(); inline bool reverse(){ if(this) rev ^= 1; } inline void pd(){ if(rev){ swap(ch[0], ch[1]); ch[0] -> reverse(); ch[1] -> reverse(); rev = false; } } inline void maintain(){ size = 1; size += ch[0] -> size; size += ch[1] -> size; } Node(); } *null = new Node, pos[200010]; Node::Node(){ ch[0] = ch[1] = null; fa = null; size = 1; rev = false; } inline int Node::which(){ if(fa == null || (fa -> ch[0] != this && fa -> ch[1] != this)) return -1; return fa -> ch[1] == this; } inline void rotate(Node *o){ Node *p = o -> fa; int l = o -> which(), r = l ^ 1; o -> fa = p -> fa; if(p -> which() != -1) p -> fa -> ch[p -> which()] = o; p -> ch[l] = o -> ch[r]; if(o -> ch[r]) o -> ch[r] -> fa = p; o -> ch[r] = p; p -> fa = o; o -> ch[r] -> maintain(); o -> maintain(); } inline void splay(Node* o){ static stack<Node*> st; if(!o) return; Node* p = o; while(1){ st.push(p); if(p -> which() == -1) break; p = p -> fa; } while(!st.empty()){ st.top() -> pd(); st.pop(); } while(o -> which() != -1){ p = o -> fa; if(p -> which() != -1){ if(p -> which() ^ o -> which()) rotate(o); else rotate(p); } rotate(o); } } inline void Access(Node* o){ Node* p = null; while(o != null){ splay(o); o -> ch[1] = p; o -> maintain(); p = o; o = o -> fa; } } inline void Link(Node* x, Node* y){ Access(x); splay(x); if(x -> ch[0]) x -> ch[0] -> fa = null; x -> ch[0] = null; x -> fa = y; x -> maintain(); } int main(){ null->ch[0]=null->ch[1]=null->fa=NULL; null->size=0; scanf("%d", &n); for(int i = 1; i <= n; i ++){ int y; scanf("%d", &y); if(i + y <= n) pos[i].fa = &pos[i + y]; } scanf("%d", &m); while(m --){ int op, x, y; scanf("%d", &op); if(op == 1){ scanf("%d", &x); x ++; Access(&pos[x]); splay(&pos[x]); printf("%d\n", pos[x].size); } else{ scanf("%d%d", &x, &y); x ++; if(x + y <= n) Link(&pos[x], &pos[x+y]); else Link(&pos[x], null); } } return 0; }