Bzoj 2002 弹飞绵羊

    xiaoxiao2021-12-14  18

    学会LCT很久了,今天才会写LCT


    因为我使用数组而不是指针来保存节点,干脆利用起了根节点的fa这个空间来保存虚边

    具体的,

    如果fa为正数,则为splay中的边。

    如果是0,没有父节点。

    如果是负数,取反之后表示虚边所指向的父亲。

    具体见代码

    #include<bits/stdc++.h> using namespace std; const int maxn = 212345; struct Node{ int fa,son[2]; int siz; void init(){ fa = son[0] = son[1] = 0; siz = 1; } void maintain(); }node[maxn]; void Node::maintain(){ siz = 1 + node[son[0]].siz + node[son[1]].siz; } int ori(int st){ if(node[st].fa < 0) return 0; return st == node[node[st].fa].son[1]; } void setc(int st,int sn,int d){ if(st > 0) node[st].son[d] = sn; if(sn > 0) node[sn].fa = st; if(st > 0) node[st].maintain(); } void zg(int x){ int st = node[x].fa; int p = node[st].fa; int d = ori(x) , dst=ori(st); setc(st,node[x].son[d^1],d); setc(x,st,d^1); setc(p,x,dst); } void splay(int x){ #define f(x) (node[x].fa) while(f(x) > 0) { if(f(f(x)) <= 0) zg(x); else{ if(ori(x) == ori(f(x))) zg(f(x)); else zg(x); zg(x); } } } void access(int x){ splay(x); while(node[x].fa < 0){ int fa = -node[x].fa; splay(fa); node[node[fa].son[1]].fa *= -1; setc(fa,x,1); splay(x); } } int fndroot(int x){ access(x); while(node[x].son[0]) x = node[x].son[0]; splay(x); return x; } void link(int st,int x){ access(x); node[x].fa = -st; access(x); } void cut(int x){ access(x); node[node[x].son[0]].fa = 0; node[x].son[0] = 0; } int main(){ int n,m; scanf("%d",&n); for(int i = 0 ; i <= n ; i++) node[i].init(); node[0].siz = 0; int x; for(int i = 1 ; i <= n; i ++){ scanf("%d",&x); if(i + x <= n) link(i+x,i); } scanf("%d",&m); int ord,v; while(m--){ scanf("%d %d",&ord,&x); x++; if(ord == 1){ access(x); printf("%d\n",node[node[x].son[0]].siz + 1); } else{ scanf("%d",&v); cut(x); if(x + v <= n) link(x+v,x); } } return 0; }
    转载请注明原文地址: https://ju.6miu.com/read-965000.html

    最新回复(0)