P3203 [HNOI2010] 弹飞绵羊

P3203 [HNOI2010] 弹飞绵羊

题目描述

某天,Lostmonkey 发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏。

游戏一开始,Lostmonkey 在地上沿着一条直线摆上 n 个装置,每个装置设定初始弹力系数 ki,当绵羊达到第 i 个装置时,它会往后弹 ki 步,达到第 i+ki 个装置,若不存在第 i+ki 个装置,则绵羊被弹飞。

绵羊想知道当它从第 i 个装置起步时,被弹几次后会被弹飞。为了使得游戏更有趣,Lostmonkey 可以修改某个弹力装置的弹力系数,任何时候弹力系数均为正整数。

输入格式

第一行包含一个整数 n,表示地上有 n 个装置,装置的编号从 0n1

接下来一行有 n 个正整数,依次为那 n 个装置的初始弹力系数。

第三行有一个正整数 m,表示操作次数。接下来 m 行每行至少有两个数 i,j

  • i=1,你要输出从编号为 j 的装置出发被弹几次后被弹飞

  • i=2,则还会再输入一个正整数 k,表示编号为 j 的弹力装置的系数被修改成 k

输出格式

对于每个 i=1 的操作,输出一行一个整数表示答案。

【数据范围】

对于 100% 的数据,1n2×1051m105

Solution:

LD再不放假让你飞起来

没想到这种题目还能用 LCT 做。我们思考一下每次重设弹力系数相当于什么:相当于断掉原来的边然后连一条 (x,x+k) 的边。所以我们开始时将每个点到对应的“着陆点”上就好了,然后注意一下因为弹飞显然是单向的,所有我们只需要让 x 认父就好了,并不需要像原来的 link 一样。然后查询就直接 access 然后 splay 就好了。我们甚至都不需要换根(显然,因为没有查询两个点的路径的需求)。

然后这道看起来很模拟的 LCT 就被我们愉快的做完了。

Code:

#include<bits/stdc++.h>
const int N=2e5+5;
using namespace std;
int n,m;
struct LCT{
struct Tree{
int tag,ff,ch[2],siz;
}t[N<<2];
int st[N];
#define ls t[x].ch[0]
#define rs t[x].ch[1]
#define fa t[x].ff
inline bool isroot(int x)
{
return (t[fa].ch[0]==x||t[fa].ch[1]==x);
}
inline void pushup(int x)
{
t[x].siz=t[ls].siz+t[rs].siz+1;
}
inline void rotate(int x)
{
int y=fa,z=t[fa].ff,k=t[fa].ch[1]==x ? 1 : 0;
if(isroot(y))t[z].ch[t[z].ch[1]==y]=x;
t[x].ff=z;
t[y].ch[k]=t[x].ch[!k];
if(t[x].ch[!k])t[t[x].ch[!k]].ff=y;
t[x].ch[!k]=y;
t[y].ff=x;
pushup(y);
}
inline void splay(int x)
{
int y=x,z=0;
while(isroot(x))
{
y=fa,z=t[fa].ff;
if(isroot(y)){rotate((t[y].ch[1]==x)==(t[z].ch[1]==y) ? y : x);}
rotate(x);
}
pushup(x);
}
void access(int x)
{
int y=0;
while(x)
{
splay(x);rs=y;pushup(x);
y=x;x=fa;
}
}
void link(int x,int y)
{
if(y<=n){t[x].ff=y;pushup(x);}
}
void cut(int x) // 这里是减去一个点 x
{
access(x),splay(x);
t[x].ch[0]=t[ls].ff=0;
}
int query(int x)
{
access(x);splay(x);
return t[x].siz;
}
}T;
void work()
{
cin>>n;
for(int i=1,tmp;i<=n;i++)
{
scanf("%d",&tmp);
T.t[i].siz=1;
T.link(i,i+tmp);
}
cin>>m;
for(int i=1,opt,x,y;i<=m;i++)
{
scanf("%d%d",&opt,&x);
x++;
if(opt&1)
{
int ans=T.query(x);
printf("%d\n",ans);
}
else
{
scanf("%d",&y);
T.cut(x);
T.link(x,x+y);
}
}
}
int main()
{
//freopen("bounce.in","r",stdin);freopen("bounce.out","w",stdout);
work();
return 0;
}
posted @   liuboom  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示