[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 ...
随机推荐
- Spring MVC之适配器的获取及执行(RequestMappingHandlerAdapter)
首先看下doDispatch()方法如何找到适合的适配器来执行方法的: protected HandlerAdapter getHandlerAdapter(Object handler) throw ...
- 小草手把手教你 LabVIEW 串口仪器控制——初识VISA串口
有些人,学习一样东西时候,喜欢现成的例子.很多人学习一门技术,都喜欢现成的例子开始,比如学单片机的啊,最开始都是修改的例子吧,学语言的也是.最开始都是模仿.这个年头看书上的理论知识太浪费时间了.所以啊 ...
- Python之旅.第三章.函数3.30
一.迭代器 1.什么是迭代?:迭代是一个重复的过程,并且每次重复都是基于上一次的结果而来2.要想了解迭代器到底是什么?必须先了解一个概念,即什么是可迭代的对象?可迭代的对象:在python中,但凡内置 ...
- java 零基础搭建dubbo运行环境
一:简介 以前做项目时,分布式环境都是其它同事在搭建,自己也没参与分布式环境搭建,只负责开发,由于近段时间工作重心转到android,java后台有一段时间没有接触了,刚好这几天有空,决定自己动 ...
- node.js的安装的配置
一.Node.js 安装配置 Node.js 提供在Windows和Linux上安装 1. Window 上安装Node.js 64 位安装包下载地址 : https://nodejs.org/di ...
- SiteMesh在项目中的配置
SiteMesh在项目中的配置 首先在web.xml里面增加siteMesh的配置: <filter> <filter-name>sitemesh</filter-nam ...
- 开源软件:NoSql数据库 - 图数据库 Neo4j
转载自原文地址:http://www.cnblogs.com/loveis715/p/5277051.html 最近我在用图形数据库来完成对一个初创项目的支持.在使用过程中觉得这种图形数据库实际上挺有 ...
- C++中explicit关键字
explicit: 防止隐式转换使用. 隐式转换:不同类型的变量可以互相转换,如将一个整形数值赋值给一个类,ClassXX lei = 4: C++中, 一个参数的构造函数(或者除了第一个参数外其余 ...
- 【原创】自己动手实现JDK动态代理
项目结构如下图所示,maven项目 1.JDK动态代理 先来一段jdk动态代理的demo, 首先创建一个接口,Person package bean; public interface Person ...
- linux系统下Apache日志分割(按天生成文件)
Apache日志按天显示,修改Apache http.conf文件,注释默认的日志文件,修改为下面2行 ErrorLog "| /usr/local/apache/bin/rotatelog ...