BZOJ2002 [Hnoi2010]Bounce 弹飞绵羊 LCT
欢迎访问~原文出处——博客园-zhouzhendong
去博客园看该题解
题目传送门 - BZOJ2002
题意概括
沿着一条直线有n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹ki步,达到第i+ki个装置,若不存在第i+ki个装置,则绵羊被弹飞。当它从第i个装置起步时,被弹几次后会被弹飞?此外,还会中途修改某个弹力装置的弹力系数,任何时候弹力系数均为正整数。
题解
几乎是LCT板子题。
首先根据输入的建树。
然后,如果是询问,那么先把n+1弄成根(rever),然后从询问的节点a向根打通一条路径(access),然后把a旋转到树根(splay),则size[ls[a]]就是答案。
如果是修改,那么就是切掉一条边再连接一条边,这就是LCT(Link_Cut_Tree)的精髓:link和cut。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | #include <cstring> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cmath> using namespace std; const int N=200005; int n,m,Next[N]; int fa[N],son[N][2],size[N],rev[N]; void pushup( int x){ size[x]=size[son[x][0]]+size[son[x][1]]+1; } bool isroot( int x){ return son[fa[x]][0]!=x&&son[fa[x]][1]!=x; } void pushdown( int x){ if (rev[x]){ rev[x]=0; rev[son[x][0]]^=1; rev[son[x][1]]^=1; swap(son[x][0],son[x][1]); } } void pushadd( int x){ if (!isroot(x)) pushadd(fa[x]); pushdown(x); } int wson( int x){ return son[fa[x]][1]==x; } void rotate( int x){ if (isroot(x)) return ; int y=fa[x],z=fa[y],L=son[y][1]==x,R=L^1; if (!isroot(y)) son[z][wson(y)]=x; fa[x]=z; fa[y]=x; fa[son[x][R]]=y; son[y][L]=son[x][R]; son[x][R]=y; pushup(y); pushup(x); } void splay( int x){ pushadd(x); for ( int y=fa[x];!isroot(x);rotate(x),y=fa[x]) if (!isroot(y)) rotate((wson(x)^wson(y))?x:y); } void access( int x){ int t=0; while (x){ splay(x); son[x][1]=t; t=x; x=fa[x]; } } void rever( int x){ access(x); splay(x); rev[x]^=1; } void link( int x, int y){ rever(x); fa[x]=y; } void cut( int x, int y){ rever(x); access(y); splay(y); fa[x]=son[y][0]=0; } int main(){ scanf ( "%d" ,&n); for ( int i=1;i<=n;i++){ scanf ( "%d" ,&Next[i]); fa[i]=Next[i]=min(i+Next[i],n+1); size[i]=1; } size[n+1]=1; memset (rev,0, sizeof rev); scanf ( "%d" ,&m); while (m--){ int op,a,b; scanf ( "%d" ,&op); if (op==1){ scanf ( "%d" ,&a),a++; rever(n+1); access(a); splay(a); printf ( "%d\n" ,size[son[a][0]]); } else { scanf ( "%d%d" ,&a,&b),a++; cut(a,Next[a]); link(a,Next[a]=min(a+b,n+1)); } } return 0; } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
· 上周热点回顾(2.17-2.23)