1. 程式人生 > >2018.10.08【HNOI2010】【BZOJ2002】【洛谷P3203】彈飛綿羊(LCT)

2018.10.08【HNOI2010】【BZOJ2002】【洛谷P3203】彈飛綿羊(LCT)

洛谷傳送門

解析:

LCTLCT裸題啊。。。

思路:

可以很顯然的發現不管怎麼變,我們設定虛擬節點n+1n+1,所有點到它的路徑構成一棵樹。

那不就完了,直接LCTLCT維護這棵路徑樹的形態,路徑上經過多少點就是要被彈多少次,在LCTLCT的節點裡維護sizsiz,最後提取路徑,siz1siz-1就是最終答案。

程式碼:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define
pc putchar
#define cs const inline int getint(){ re int num; re char c; while(!isdigit(c=gc()));num=c^48; while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48); return num; } inline void outint(int a){ static char ch[13]; if(a==0)pc('0'); while(a)ch[++ch[0]]=a-a/10*10,a/=10; while(ch[0])
pc(ch[ch[0]--]^48); } typedef struct splay_node *point; struct splay_node{ point son[2],fa; int siz; bool tag; point &lc(){return son[0];} point &rc(){return son[1];} bool which(){return fa->son[1]==this;} bool isroot(){return !fa||(fa->son[0]!=this&&fa->son[1]!=this
);} void pushdown(){ if(tag){ swap(son[0],son[1]); if(son[0])son[0]->tag^=1; if(son[1])son[1]->tag^=1; tag=0; } } void pushup(){ siz=(son[0]?son[0]->siz:0)+(son[1]?son[1]->siz:0)+1; } }; cs int N=200005; struct Link_Cut_Tree{ splay_node ttt[N]; void Rotate(point now){ point Fa=now->fa,FA=Fa->fa; bool pos=now->which(); if(FA&&!Fa->isroot())FA->son[Fa->which()]=now; now->fa=FA; Fa->fa=now; Fa->son[pos]=now->son[!pos]; if(Fa->son[pos])Fa->son[pos]->fa=Fa; now->son[!pos]=Fa; Fa->pushup(); now->pushup(); } void Splay(point now){ static point q[N]; static int qn; q[qn=1]=now; for(point Fa=now;!Fa->isroot();Fa=Fa->fa)q[++qn]=Fa->fa; for(int re i=qn;i;--i)q[i]->pushdown(); for(point Fa;!now->isroot();Rotate(now)) if(!(Fa=now->fa)->isroot())Rotate(now->which()==Fa->which()?Fa:now); } void access(point now){ for(point son=NULL;now;son=now,now=now->fa) Splay(now),now->rc()=son,now->pushup(); } void makeroot(point now){ access(now),Splay(now),now->tag^=1; } void link(point u,point v){ makeroot(u),u->fa=v; } void link(int u,int v){link(&ttt[u],&ttt[v]);} void cut(point u,point v){ makeroot(u),access(v),Splay(v); v->lc()=u->fa=NULL; } void cut(int u,int v){cut(&ttt[u],&ttt[v]);} int query(point u,point v){ makeroot(u),access(v),Splay(v); return v->siz-1; } int query(int u,int v){return query(&ttt[u],&ttt[v]);} }LCT; int n,m; int val[N]; signed main(){ n=getint(); for(int re i=1;i<=n;++i){ val[i]=getint(); int to=(val[i]+i>n)?(n+1):(val[i]+i); LCT.link(i,to); } m=getint(); while(m--){ int op=getint(); int x=getint()+1; switch(op){ case 1:{ outint(LCT.query(x,n+1));pc('\n'); break; } case 2:{ int k=getint(); int to=(val[x]+x>n)?(n+1):(val[x]+x); LCT.cut(x,to); val[x]=k;to=(val[x]+x>n)?(n+1):(val[x]+x); LCT.link(x,to); break; } } } return 0; }