题目:

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的情况,你都要输出一个需要的步数,占一行。

题解:

我们将每个坐标视作一个点

对于每一个\(a_i我们将其视为连接\)(i+a_i,i)\(的一条树边.
表示可以从点i到达点\)(i+a_i)\(对于所有的\)(i+a_i) > n$我们令其为n+1

然后对于每一次询问x,即查询以x为根的时候点(n+1)的深度。

又要求支持修改,所以我们大力上LCT即可.

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
typedef long long ll;
inline void read(int &x){
x=0;char ch;bool flag = false;
while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
const int maxn = 200010;
int n;
namespace Splay{
struct Node{
Node *ch[2],*fa;
int siz;
void update(){
siz = ch[0]->siz + ch[1]->siz + 1;
}
}*null;
Node mem[maxn],*it;
inline void init(){
it = mem;null = it++;null->ch[0] = null->ch[1] = null;
null->fa = null;null->siz = 0;
}
inline Node* newNode(){
Node *p = it++;p->ch[0] = p->ch[1] = p->fa = null;
p->siz = 1;return p;
}
inline void rotate(Node *p,Node *x){
int k = p == x->ch[1];
Node *y = p->ch[k^1],*z = x->fa;
if(z->ch[0] == x) z->ch[0] = p;
if(z->ch[1] == x) z->ch[1] = p;
if(y != null) y->fa = x;
p->fa = z;p->ch[k^1] = x;
x->fa = p;x->ch[k] = y;
x->update();p->update();
}
inline bool isroot(Node *p){
return p == null || (p->fa->ch[0] != p && p->fa->ch[1] != p);
}
inline void splay(Node *p){
while(!isroot(p)){
Node *x = p->fa,*y = x->fa;
if(isroot(x)) rotate(p,x);
else if(p == x->ch[0] ^ x == y->ch[0]) rotate(p,x),rotate(p,y);
else rotate(x,y),rotate(p,x);
}p->update();
}
}
namespace LCT{
inline void init(){
Splay::init();
for(int i=1;i<=n+1;++i) Splay::newNode();
}
using namespace Splay;
inline void Access(Node *u){
Node *v = null;
while(u != null){
splay(u);u->ch[1] = v;
v = u;u = u->fa;
}
}
inline void link(Node *u,Node *v){
Access(v);splay(v);
v->fa = u;
}
inline void cut(Node *u,Node *v){
Access(u);splay(u);
Access(v);splay(v);
splay(u);u->ch[1] = u->ch[1]->fa = null;
}
inline int query(Node *x){
Access(x);splay(x);
return x->ch[0]->siz;
}
}
int a[maxn];
int main(){
read(n);LCT::init();
for(int i=1;i<=n;++i){
read(a[i]);
LCT::link(Splay::mem+min(i+a[i],n+1),Splay::mem+i);
}
int m;read(m);
while(m--){
int u,v;read(u);
if(u == 1){
read(u); ++ u;
if(u > n) continue;
printf("%d\n",LCT::query(Splay::mem + u));
}else{
read(u);read(v);++ u;
LCT::cut(Splay::mem+min(u+a[u],n+1),Splay::mem+u);
LCT::link(Splay::mem+min(u+v,n+1),Splay::mem+u);
a[u] = v;
}
}
getchar();getchar();
return 0;
}

bzoj 2002: 弹飞绵羊 Link-Cut-Tree的更多相关文章

  1. [BZOJ 2002] [HNOI2010]弹飞绵羊(Link Cut Tree)

    [BZOJ 2002] [HNOI2010]弹飞绵羊(Link Cut Tree) 题面 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一 ...

  2. BZOJ 2002 弹飞绵羊(分块)

    题目:弹飞绵羊 这道题,据说是lct裸题,但是lct那么高级的数据结构,我并不会,所以采取了学长讲过的分块做法,我们对序列分块,可以定义两个数组,其中一个表示从当前位置跳出当前块需要多少步,另一个数组 ...

  3. [bzoj] 2002 弹飞绵羊 || LCT

    原题 简单的LCT练习题. 我们发现对于一个位置x,他只能跳到位置x+k,也就是唯一的父亲去.加入我们将弹飞的绵羊定义为跳到了n+1,那么这就形成了一棵树.而因为要修改k,所以这颗树是动态连边的,那么 ...

  4. BZOJ 2002 弹飞绵羊

    LCT 刚学LCT,对LCT的性质不太熟练,还需要多多练习.. 对每一个点,将其与它能够到达的点连一条虚边.弹出去的话就用n+1这个节点表示. 第一种操作我们需要从LCT的性质入手,问的问题其实就是x ...

  5. bzoj 2002 弹飞绵羊 lct裸题

    上一次用分块过了, 今天换了一种lct(link-cut tree)的写法. 学lct之前要先学过splay. lct 简单的来说就是 一颗树, 然后每次起作用的都是其中的某一条链. 所以每次如果需要 ...

  6. bzoj 2002 弹飞绵羊 分块

    正解lct,然而本蒟蒻并不会.... 分块思路很清晰,处理出每个点弹出所在块所需要的步数及出去后的第一个位置 #include<cstdio> #include<cstring> ...

  7. 【BZOJ2002】弹飞绵羊(Link-Cut Tree)

    [BZOJ2002]弹飞绵羊(Link-Cut Tree) 题面 题目描述 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始,Lost ...

  8. 【BZOJ 2002】【Hnoi 2010】弹飞绵羊 分块||Link Cut Tree 两种方法

    ShallWe,Yveh,hmy,DaD3zZ,四人吃冰糕从SLYZ超市出来后在马路上一字排开,,,吃完后发现冰糕棍上写着:“向狮子座表白:愿做你的小绵羊”,,, 好吧在这道题里我们要弹飞绵羊,有分块 ...

  9. bzoj 2002 Bounce 弹飞绵羊

    bzoj 2002 Bounce 弹飞绵羊 设一个虚拟节点表示被弹飞,则每个点的后继点是唯一确定的,每个点向它的后继点连边,就形成了一颗树. 询问就是问某个节点到虚拟节点的路径长度,修改就删除原来向后 ...

随机推荐

  1. 使用Socket通信实现FTP客户端程序

    FTP 客户端如 FlashFXP,File Zilla 被广泛应用,原理上都是用底层的 Socket 来实现.FTP 客户端与服务器端进行数据交换必须建立两个套接字,一个作为命令通道,一个作为数据通 ...

  2. 实用T-SQL代码

    1.根据出生日期计算当前已满周岁 DECLARE @birth datetime SET @birth='1990-01-01' ),) ),) 2.COUNT(expression) just re ...

  3. lua2json

    lua对象json序列化,很简单,没做中文的unicode编码了 local function bool2json(v) return v and "true" or " ...

  4. 洛谷 P3216 [HNOI2011]数学作业

    最近学了矩阵,kzj大佬推荐了我这一道题目. 乍一眼看上去,没看出是矩阵,就随便打了一个暴力,30分. 然后仔细分析了一波,发现蛮简单的. 结果全wa了,先看看下面的错误分析吧! 首先,设f[n]为最 ...

  5. Django 模型系统(model)&ORM--进阶

    QuerySet 可切片 使用Python 的切片语法来限制查询集记录的数目 .它等同于SQL 的LIMIT 和OFFSET 子句. >>> Entry.objects.all()[ ...

  6. mysql用户和权限管理(Linux系统下)

    在mysql自带的库中有一个mysql,这个库包含了太多的东西,其中有一张表user,这张表存储了所有的用户信息. mysql> select user,host,password from u ...

  7. Zookeeper启动Permission denied

    Zookeeper 查询状态,出现如下问题: JMX enabled by default Using config: /usr/zookeeper/zookeeper-/bin/../conf/zo ...

  8. 【Flask模板】宏的概念和基本使用

    # 宏:模板中的宏跟python中的函数类似,可以传递参数,但是不能有返回值,可以将一些经常用到的代码片段放到宏中,然后把一些不固定的值抽取出来当成一个变量.使用宏的时候,参数可以为默认值.相关示例代 ...

  9. 20145229吴姗珊 《Java程序设计》第4周学习总结

    20145229吴姗珊 <Java程序设计>第4周学习总结 教材学习内容总结 第六章 继承与多态 6.1继承共同行为 1.继承基本上就是避免多个类间重复定义共同行为 简单的类的定义 使用s ...

  10. poj 1144 Network 【求一个网络的割点的个数 矩阵建图+模板应用】

    题目地址:http://poj.org/problem?id=1144 题目:输入一个n,代表有n个节点(如果n==0就结束程序运行). 在当下n的这一组数据,可能会有若干行数据,每行先输入一个节点a ...