博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ2002:[HNOI2010]弹飞绵羊——题解
阅读量:6230 次
发布时间:2019-06-21

本文共 2708 字,大约阅读时间需要 9 分钟。

某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏。游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹ki步,达到第i+ki个装置,若不存在第i+ki个装置,则绵羊被弹飞。绵羊想知道当它从第i个装置起步时,被弹几次后会被弹飞。为了使得游戏更有趣,Lostmonkey可以修改某个弹力装置的弹力系数,任何时候弹力系数均为正整数。

因为它的标签有LCT所以应该是用LCT写的。

因为每个弹射器之间不可能存在环(因为你只能往后跳)所以弹射器和弹飞点(记为n+1)构成了一片森林。

这样我们先link(i,min(i+k[i],n+1)。

对于修改操作显然先cut原先的边在按上面方法link即可。

对于查询我们就是相当于求n+1和i的路径长,先makeroot(n+1),再access(i),这样n+1到i的实边长度即为所求,然后求实链所代表的平衡树大小-1即可。

(下面为吐槽)

说实话最开始没想到LCT怎么求两点最短路。

但是后来一想这不就是access一下之后求实边长度吗。

再看了洛谷超易懂题解发现实链不就是一棵平衡树吗,求一遍平衡树大小-1不就得了?

(假装这题很简单)

#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;const int N=2e5+10;int n,m,r,k[N],fa[N],tr[N][2],rev[N],q[N],size[N];inline int read(){ int X=0,w=0;char ch=0; while(!isdigit(ch)){w|=ch=='-';ch=getchar();} while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X;}inline bool get(int x){ return tr[fa[x]][1]==x;}inline bool isroot(int x){ if(!fa[x])return 1; return tr[fa[x]][0]!=x&&tr[fa[x]][1]!=x;}inline void upt(int x){ size[x]=1; if(tr[x][0])size[x]+=size[tr[x][0]]; if(tr[x][1])size[x]+=size[tr[x][1]];}inline void pushrev(int x){ if(!rev[x])return; swap(tr[x][0],tr[x][1]); if(tr[x][0])rev[tr[x][0]]^=1; if(tr[x][1])rev[tr[x][1]]^=1; rev[x]=0;}inline void rotate(int x){ int y=fa[x],z=fa[y],b=tr[y][0]==x?tr[x][1]:tr[x][0]; if(z&&!isroot(y))(tr[z][0]==y?tr[z][0]:tr[z][1])=x; fa[x]=z;fa[y]=x;b?fa[b]=y:0; if(tr[y][0]==x)tr[x][1]=y,tr[y][0]=b; else tr[x][0]=y,tr[y][1]=b; upt(y);upt(x);}inline void splay(int x){ q[r=0]=x; for(int y=x;!isroot(y);y=fa[y])q[++r]=fa[y]; for(int i=r;i>=0;i--)pushrev(q[i]); while(!isroot(x)){ if(!isroot(fa[x])) rotate((get(x)==get(fa[x])?fa[x]:x)); rotate(x); } upt(x);}inline void access(int x){ for(int y=0;x;y=x,x=fa[x]){ splay(x);tr[x][1]=y; if(y)fa[y]=x; }}inline int findroot(int x){ access(x);splay(x); while(pushrev(x),tr[x][0])x=tr[x][0]; splay(x); return x;}inline void makeroot(int x){ access(x);splay(x); rev[x]^=1;}inline void link(int x,int y){ makeroot(x);fa[x]=y;}inline void cut(int x,int y){ makeroot(x);access(y);splay(y); tr[y][0]=0;fa[x]=0;}int main(){ n=read(); for(int i=1;i<=n;i++) link(i,min(i+(k[i]=read()),n+1)); m=read(); for(int i=1;i<=m;i++){ int op=read(),j=read()+1; if(op==1){ makeroot(j);access(n+1);splay(n+1); printf("%d\n",size[n+1]-1); }else{ cut(j,min(j+k[j],n+1)); link(j,min(j+(k[j]=read()),n+1)); } } return 0;}

+++++++++++++++++++++++++++++++++++++++++++

 +本文作者:luyouqi233。               +

 +欢迎访问我的博客:+

+++++++++++++++++++++++++++++++++++++++++++

转载于:https://www.cnblogs.com/luyouqi233/p/8469602.html

你可能感兴趣的文章
“云计算”让城市智慧起来
查看>>
Google计划收购数据科学社区Kaggle
查看>>
《OpenGL ES应用开发实践指南:Android卷》—— 1.3 初始化OpenGL
查看>>
Java 生成 PDF 文档
查看>>
C语言实现栈的基本操作
查看>>
策略模式
查看>>
linux(6.8版本最小化安装)安装nginx实战
查看>>
我的友情链接
查看>>
检讨~
查看>>
html引用公共的html文件
查看>>
关于Java泛型使用的问题记录
查看>>
进入Android Dalvik虚拟机之Dalvik虚拟机的特点
查看>>
while的四种使用方式
查看>>
nginx添加几十个域名
查看>>
SpringMVC同时支持多视图(JSP,Velocity,Freemarker等)的一种思路实现
查看>>
致初入模板创作:了解各种浏览器真正的核心,测试模板兼容时就不用开这么多浏览器...
查看>>
我的友情链接
查看>>
利用rsync备份邮件系统
查看>>
java.io.Serializable浅析
查看>>
分布式计算
查看>>