弹飞绵羊

LCT
暴力建图后只有cut link
建个超级点
次数即size

# include <stdio.h>
# include <stdlib.h>
# include <iostream>
# include <algorithm>
# include <string.h>
# define IL inline
# define RG register
# define Fuck(a) a > n ? n + 1 : a
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long ll;

IL ll Read(){
    RG char c = getchar(); RG ll x = 0, z = 1;
    for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
    for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + c - '0';
    return x * z;
}

const int MAXN(2e5 + 10);
int S[MAXN], n, m, k[MAXN];
struct Tree{  int fa, ch[2], rev, size;  } t[MAXN];

IL bool Son(RG int x){  return t[t[x].fa].ch[1] == x;  }

IL bool Isroot(RG int x){  return t[t[x].fa].ch[0] != x && t[t[x].fa].ch[1] != x;  }

IL void Update(RG int x){  t[x].size = 1 + t[t[x].ch[0]].size + t[t[x].ch[1]].size;  }

IL void Pushdown(RG int x){  if(!t[x].rev) return; t[x].rev = 0; t[t[x].ch[0]].rev ^= 1; t[t[x].ch[1]].rev ^= 1; swap(t[x].ch[0], t[x].ch[1]);  }

IL void Rot(RG int x){
    RG int y = t[x].fa, z = t[y].fa, c = Son(x);
    if(!Isroot(y)) t[z].ch[Son(y)] = x; t[x].fa = z;
    t[y].ch[c] = t[x].ch[!c]; t[t[y].ch[c]].fa = y;
    t[x].ch[!c] = y; t[y].fa = x;
    Update(y);
}

IL void Splay(RG int x){
    RG int top = 0; S[++top] = x;
    for(RG int y = x; !Isroot(y); y = t[y].fa) S[++top] = t[y].fa;
    while(top) Pushdown(S[top--]);
    for(RG int y = t[x].fa; !Isroot(x); Rot(x), y = t[x].fa)
        if(!Isroot(y)) Son(x) ^ Son(y) ? Rot(x) : Rot(y);
    Update(x);
}

IL void Access(RG int x){  for(RG int y = 0; x; y = x, x = t[x].fa) Splay(x), t[x].ch[1] = y, Update(x);  }

IL int Findroot(RG int x){  Access(x); Splay(x); while(t[x].ch[0]) x = t[x].ch[0]; return x;  }

IL void Makeroot(RG int x){  Access(x); Splay(x); t[x].rev ^= 1;  }

IL void Split(RG int x, RG int y){  Makeroot(x); Access(y); Splay(y);  }

IL void Link(RG int x, RG int y){  Makeroot(x); t[x].fa = y;  }

IL void Cut(RG int x, RG int y){  Split(x, y); t[y].ch[0] = t[x].fa = 0;  }

IL int Query(RG int x, RG int y){  Split(x, y); return t[y].size;  }

int main(RG int argc, RG char* argv[]){
    n = Read();
    for(RG int i = 1; i <= n; i++) k[i] = Read(), Link(i, Fuck(i + k[i]));
    m = Read();
    while(m--){
        RG int i;
        if(Read() == 1) i = Read() + 1, printf("%d
", Query(i, n + 1) - 1);
        else{
            i = Read() + 1; Cut(i, Fuck(i + k[i])); k[i] = Read();
            if(Findroot(i) != Findroot(Fuck(i + k[i]))) Link(i, Fuck(i + k[i]));
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/cjoieryl/p/8206378.html