HNOI2010 弹飞绵羊 发表于 2018-08-09 | 分类于 各省省选 | 字数统计: 588 字 题目链接 题解LCT模板题。把跳到的点当作是父亲,支持删边和连边即可。123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cctype>#define INF 2000000000using namespace std;typedef long long ll;int read(){ int f=1,x=0;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();} while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar(); return f*x; }int n,m,fa[200005]={0},ch[200005][2],siz[200005]={0},rev[200005]={0};int val[200005],to[200005];int cmp(int k){ return ch[fa[k]][1]==k;}int isroot(int k){ return ch[fa[k]][0]!=k&&ch[fa[k]][1]!=k;}void Rev(int k){ swap(ch[k][0],ch[k][1]); rev[k]^=1;}void maintain(int k){ siz[k]=siz[ch[k][0]]+siz[ch[k][1]]+1;}void pushdown(int k){ if(k&&rev[k]){ rev[k]=0; if(ch[k][0])Rev(ch[k][0]); if(ch[k][1])Rev(ch[k][1]); }}void pushup(int k){ if(!k)return ; if(!isroot(k))pushup(fa[k]); pushdown(k);} void Rotate(int k){ int Fa=fa[k],Gfa=fa[Fa],d=cmp(k); ch[Fa][d]=ch[k][d^1],fa[ch[k][d^1]]=Fa; ch[k][d^1]=Fa,fa[Fa]=k; fa[k]=Gfa; if(!isroot(Fa)){ if(Fa==ch[Gfa][0])ch[Gfa][0]=k; else if(Fa==ch[Gfa][1])ch[Gfa][1]=k; } maintain(Fa); }void splay(int k){ pushup(k); for(int Fa=fa[k];!isroot(k);Rotate(k),Fa=fa[k]) if(fa[Fa]&&!isroot(Fa))Rotate(cmp(k)==cmp(Fa)?Fa:k); maintain(k);} void access(int k){ for(int t=0;k;t=k,k=fa[k])splay(k),ch[k][1]=t,maintain(k);} void makeroot(int k){ access(k),splay(k),Rev(k);}int findroot(int k){ while(fa[k])k=fa[k];return k;}void Split(int u,int v){ makeroot(u),access(v),splay(v);}void cut(int u,int v){ Split(u,v); ch[v][0]=fa[u]=0; maintain(v);}void link(int u,int v){ makeroot(u),fa[u]=v;}void init(){ n=read(),siz[n+1]=1; for(int i=1;i<=n;i++)val[i]=read(),to[i]=min(n+1,i+val[i]),siz[i]=1; for(int i=1;i<=n;i++)link(i,to[i]); }void solve(){ m=read(); int opr,x,y; while(m--){ opr=read(),x=read()+1; if(opr==1) Split(x,n+1),printf("%d\n",siz[n+1]-1); if(opr==2){ y=read(); if(to[x]==n+1&&x+y>n)continue; cut(x,to[x]),val[x]=y,to[x]=min(x+y,n+1),link(x,to[x]); } }}int main(){ init(); solve(); return 0;}
v1.5.2