[HNOI2010]弹飞绵羊
Description
某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏。游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹ki步,达到第i+ki个装置,若不存在第i+ki个装置,则绵羊被弹飞。绵羊想知道当它从第i个装置起步时,被弹几次后会被弹飞。为了使得游戏更有趣,Lostmonkey可以修改某个弹力装置的弹力系数,任何时候弹力系数均为正整数。
Input
第一行包含一个整数n,表示地上有n个装置,装置的编号从0到n-1,接下来一行有n个正整数,依次为那n个装置的初始弹力系数。第三行有一个正整数m,接下来m行每行至少有两个数i、j,若i=1,你要输出从j出发被弹几次后被弹飞,若i=2则还会再输入一个正整数k,表示第j个弹力装置的系数被修改成k。对于20%的数据n,m<=10000,对于100%的数据n<=200000,m<=100000
Output
对于每个i=1的情况,你都要输出一个需要的步数,占一行。
Sample Input
1 2 1 1
3
1 1
2 1 1
1 1
Sample Output
2
3
先建树,如果i+k大于n,就和n+1,建边表示弹出,否则和i+k建边
建树用LCT的link操作
修改就cut操作删掉旧边,加上新边
查询时,把n+1变为树根,把x到n+1都变为实根
查询路径上节点数-1输出
splay维护size,因为总是只有一颗完整的树,所以不需要判断cut和link操作的可行性
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int size[],ch[][],rev[],pre[],isrt[],n,m,k[];
void pushup(int o)
{
if (!o) return;
size[o]=size[ch[o][]]+size[ch[o][]]+;
}
void pushdown(int o)
{
if (!o) return;
if (rev[o])
{
int ls=ch[o][],rs=ch[o][];
rev[ls]^=;
swap(ch[ls][],ch[ls][]);
rev[rs]^=;
swap(ch[rs][],ch[rs][]);
rev[o]=;
}
}
void push(int o)
{
if (isrt[o]==) push(pre[o]);
pushdown(o);
}
void rotate(int o,bool kind)
{
int p=pre[o];
ch[p][!kind]=ch[o][kind];pre[ch[o][kind]]=p;
if (isrt[p]) isrt[p]=,isrt[o]=;
else ch[pre[p]][ch[pre[p]][]==p]=o;
pre[o]=pre[p];
ch[o][kind]=p;pre[p]=o;
pushup(p);pushup(o);
}
void splay(int o)
{
push(o);
while (isrt[o]==)
{
if (isrt[pre[o]])
rotate(o,ch[pre[o]][]==o);
else
{
int p=pre[o],kind=ch[pre[p]][]==p;
if (ch[p][kind]==o)
rotate(o,!kind),rotate(o,kind);
else rotate(p,kind),rotate(o,kind);
}
}
}
void access(int o)
{
int y=;
while (o)
{
splay(o);
isrt[ch[o][]]=;
isrt[ch[o][]=y]=;
pushup(o);
y=o;o=pre[o];
}
}
void makeroot(int o)
{
access(o);
splay(o);
rev[o]^=;
swap(ch[o][],ch[o][]);
}
void link(int x,int y)
{
makeroot(x);
pre[x]=y;
}
void cut(int x,int y)
{
makeroot(x);
access(y);splay(y);
ch[y][]=;pre[x]=;
isrt[x]=;
pushup(y);
}
int main()
{int i,c,x,y,st,ed;
cin>>n;
for (i=;i<=n+;i++)
isrt[i]=,size[i]=;
for (i=;i<=n;i++)
{
scanf("%d",&k[i]);
if (i+k[i]>n) link(i,n+);
else link(i,i+k[i]);
}
cin>>m;
for (i=;i<=m;i++)
{
scanf("%d",&c);
if (c==)
{
scanf("%d",&x);x++;
makeroot(n+);
access(x);
splay(x);
printf("%d\n",size[x]-);
}
else
{
scanf("%d%d",&x,&y);x++;
if (k[x]+x>n) st=n+;
else st=k[x]+x;
if (y+x>n) ed=n+;
else ed=y+x;
k[x]=y;
if (st!=ed)
{
cut(x,st);
link(x,ed);
}
}
}
}
LCT
还有分块的做法
把n个点分成$sqrt n$块
预处理出f[i],s[i]
f[i]表示i会跳到下一块的地方
s[i]表示i跳到f[i]所需要的步数
查询时直接往后跳,最多跳$sqrt n$块
修改时只修改那一块$sqrt n$个元素
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int n,k[],lim,s[],f[],m;
int main()
{int i,j,opt,x,now,cnt,y;
cin>>n;
for (i=;i<=n;i++)
{
scanf("%d",&k[i]);
}
lim=sqrt(n);
for (i=;i<=n;i+=lim)
{
for (j=min(n,i+lim-);j>=i;j--)
{
if (k[j]+j>min(n,i+lim-)) s[j]=,f[j]=k[j]+j;
else s[j]=s[j+k[j]]+,f[j]=f[k[j]+j];
}
}
cin>>m;
for (i=;i<=m;i++)
{
scanf("%d%d",&opt,&x);x++;
if (opt==)
{
cnt=;
while (x<=n)
{
cnt+=s[x];
x=f[x];
}
printf("%d\n",cnt);
}
else
{
scanf("%d",&y);
k[x]=y;
if (x%lim==) now=x-lim+;
else now=x-x%lim+;
for (j=min(n,now+lim-);j>=now;j--)
{
if (k[j]+j>min(n,now+lim-)) s[j]=,f[j]=k[j]+j;
else s[j]=s[j+k[j]]+,f[j]=f[k[j]+j];
}
}
}
}
分块
[HNOI2010]弹飞绵羊的更多相关文章
- P3203 [HNOI2010]弹飞绵羊(LCT)
P3203 [HNOI2010]弹飞绵羊 LCT板子 用一个$p[i]$数组维护每个点指向的下个点. 每次修改时cut*1+link*1就解决了 被弹出界时新设一个点,权为0,作为终点表示出界点.其他 ...
- [HNOI2010] 弹飞绵羊 (分块)
[HNOI2010] 弹飞绵羊 题目描述 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始,Lostmonkey在地上沿着一条直线摆上 ...
- 洛谷 P3203 [HNOI2010]弹飞绵羊 解题报告
P3203 [HNOI2010]弹飞绵羊 题目描述 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始,Lostmonkey在地上沿着一 ...
- [BZOJ 2002] [HNOI2010]弹飞绵羊(Link Cut Tree)
[BZOJ 2002] [HNOI2010]弹飞绵羊(Link Cut Tree) 题面 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一 ...
- 「洛谷P3202」[HNOI2010]弹飞绵羊 解题报告
P3203 [HNOI2010]弹飞绵羊 题目描述 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始,Lostmonkey在地上沿着一 ...
- [Luogu P3203] [HNOI2010]弹飞绵羊 (LCT维护链的长度)
题面 传送门:洛谷 Solution 这题其实是有类似模型的. 我们先考虑不修改怎么写.考虑这样做:每个点向它跳到的点连一条边,最后肯定会连成一颗以n+1为根的树(我们拿n+1代表被弹出去了).题目所 ...
- P3203 [HNOI2010]弹飞绵羊 —— 懒标记?分块?LCT?...FAQ orz
好久没写博客了哈,今天来水一篇._(:з」∠)_ 题目 :弹飞绵羊(一道省选题) 题目描述 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏 ...
- P3203 [HNOI2010]弹飞绵羊 —— 懒标记?分块?
好久没写博客了哈,今天来水一篇._(:з」∠)_ 题目 :弹飞绵羊(一道省选题) 题目描述 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏 ...
- 洛谷P3203 [HNOI2010] 弹飞绵羊 [LCT]
题目传送门 弹飞绵羊 题目描述 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置, ...
- P3203 [HNOI2010]弹飞绵羊(LCT)
弹飞绵羊 题目传送门 解题思路 LCT. 将每个节点的权值设为\(1\),连接\(i\)和\(i+ki\),被弹飞就连上\(n\),维护权值和\(sum[]\).从\(j\)弹飞需要的次数就是\(sp ...
随机推荐
- alpha冲刺第八天
一.合照 二.项目燃尽图 三.项目进展 首页文章显示部分 首页小功能福大地图完成 四.明日规划 发现爬取的数据是一整个网页的内容,而我们需要的仅仅是教务处通知的文章,在筛选方面还需要改进,查找如何进行 ...
- Alpha冲刺No.5
一.站立式会议 在助教帮助下,优先解决404的问题,将demo移植到自己项目上. 进一步制作界面. 将已做好的内容,移植到手机做部分测试,能够在同一路由子网内登录数据库. 二.实际项目进展 已经解决了 ...
- C语言--第14.15周作业
一. 7-3 将数组中的数逆序存放 1.代码 #include 2<stdio.h> int main() { int a[10]; int i, n, s; scanf("%d ...
- verilog学习笔记(0)
assign赋值语句根本不允许出现在always语句块中 位于begin/end块内的多条阻塞赋值语句是串行执行的; 但是多条非阻塞赋值语句却是并行执行的,这些非阻塞赋值语句都会在其中任何一条语句执行 ...
- 基于协程的Python网络库gevent
import gevent def test1(): print 12 gevent.sleep(0) print 34 def test2(): print 56 gevent.sleep(0) p ...
- iOS开发-OC数据类型
以下是OC中的实例,Swift部分不适用 iOS中的注释 // 单行注释 // 注释对代码起到解释说明的作用,注释是给程序员看的,不参与程序运行 /* 多行注释 Xcode快捷键 全选 cm ...
- 亚马逊AWS学习——EC2的自定义VPC配置
1 网络配置 EC2即亚马逊AWS云服务中的虚拟主机.创建EC2实例时如果使用的默认VPC并分配了公有IP是可以上网的.但我们经常需要自定义的网络环境,这时就需要自己定义VPC和子网了. 1.1 配置 ...
- bzoj 4373 算术天才⑨与等差数列
4373: 算术天才⑨与等差数列 Time Limit: 10 Sec Memory Limit: 128 MBhttp://www.lydsy.com/JudgeOnline/problem.ph ...
- 自制 h5 音乐播放器 可搜索
闲言碎语: 有好几天没有发表博客了,这也是因为一直开发音乐和完善我的博客项目,好不容易抽出时间总结一下这几天所做的东西,笔试又不断通知,实则匆忙 今天难得逃了一次课,就趁这时间,该写写就写写吧~~ 进 ...
- EasyUI 中datagrid 分页。
注释:datagrid分页搞了好几天才完全搞好,网上没完全的资料.明天晚上贴代码. 睡觉.