4764: 弹飞大爷

Time Limit: 30 Sec  Memory Limit: 256 MB
Submit: 4  Solved: 4
[Submit][Status][Discuss]

Description

自从WC退役以来,大爷是越来越懒惰了。为了帮助他活动筋骨,也是受到了弹飞绵羊一题的启发,机房的小伙伴们
决定齐心合力构造一个下面这样的序列。这个序列共有N项,每项都代表了一个小伙伴的力量值,如果大爷落到了
第i个小伙伴的手里,那么第i个小伙伴会把大爷弹到第i+ai个小伙伴手里,其中ai就是第i个小伙伴的力量值,也
就是序列的第i项。然而,因为大爷太沉了,所以有些小伙伴不能撑到锻(you)炼(xi)结束,所以我们中途会替
换一些小伙伴,也就是改变序列的某些项。而且,因为大爷太沉了,所以有些小伙伴不能把大爷扔向前方,而是会
把大爷往反方向扔,也就是序列中的一些项会是负的(当然,也可能是零喽)。现在机智的大爷通过在空中的观察
,已经知道小伙伴们的所有活动——即初始序列、所有更改操作,他想请你算一算,如果他在某时刻落到了某个位
置,那么他会在几次弹起之后落到小伙伴序列之外(毕竟摔在地上还是蛮疼的)。

Input

第一行为两个整数N和M,代表序列长度和操作次数。
第二行为N个整数,代表初始的小伙伴序列。
接下来有M行,每行代表一个操作。
如果这一行的第一个数是1,代表该操作是一个询问操作,接下来一个数X,代表询问此时大爷从X处,经过几次弹
起会摔在地上。如果永远不会摔在地上,请输出-1。
如果这一行的第一个数是2,代表该操作是一个更改操作,接下来两个数X,Y,代表将序列的第X项改为Y。
N,M <= 200000  |Ai| < N
 

Output

对于每次询问操作,输出弹起次数或-1。
 

Sample Input

3 19
1 1 1
1 1
1 2
1 3
2 1 2
1 1
1 2
1 3
2 3 -1
1 1
1 2
1 3
2 2 233
1 1
1 2
1 3
2 2 -233
1 1
1 2
1 3

Sample Output

3
2
1
2
2
1
-1
-1
-1
3
1
2
3
1
2

HINT

 

Source

[Submit][Status][Discuss]

今天偶然看到了某童鞋的弹飞绵羊的分块做法,十分不爽,想法卡他,然后就有了这道题,反正我觉得原来的分块方法是绝望了。但是万万木有想到,这道题依然有非LCT做法,比如大爷的Split Treap做法等等。

作为此题的出题人之一,其实我只负责题面部分和代码,解法都是ZZ和LH想的,和我没有半毛钱关系。

考虑怎么继续沿用弹飞绵羊的LCT做法,发现可能产生环,很烦。但是可以通过把环上的一条断掉,使得其在LCT中仍然是一棵树,我们把这条被“隐藏”起来的边标记在该树的Root上。那么每次加入边的时候,现考虑一下是否会形成环,如果会,就按照上面的方法处理。然后还有断边操作,只需要考虑一下断掉这条边后,是否会使得Root上的隐藏边重新显现即可。

不爽的是,刚刚放到大视野上一个下午,std就被LincHpin和Claris踩了。开心的是,至少我数据应该没造错。

 #include <bits/stdc++.h>

 const int mxn = ;

 int tag[mxn];
int rev[mxn];
int siz[mxn];
int fat[mxn];
int son[mxn][]; inline bool isRoot(int t)
{
int f = fat[t]; if (!f)
return true; if (son[f][] == t)
return false;
if (son[f][] == t)
return false; return true;
} inline void update(int t)
{
siz[t] = ; if (son[t][])
siz[t] += siz[son[t][]];
if (son[t][])
siz[t] += siz[son[t][]];
} inline void connect(int f, int t, int s)
{
if (t)
fat[t] = f;
if (f)
son[f][s] = t;
} inline void rotate(int t)
{
int f = fat[t];
int g = fat[f];
int s = son[f][] == t; connect(f, son[t][!s], s);
connect(t, f, !s); fat[t] = g;
if (g && son[g][] == f)
son[g][] = t;
if (g && son[g][] == f)
son[g][] = t; update(f);
update(t);
} inline void push(int t)
{
if (rev[t])
{
rev[t] = ; if (son[t][])
rev[son[t][]] ^= ;
if (son[t][])
rev[son[t][]] ^= ; std::swap(son[t][], son[t][]);
}
} inline void pushdown(int t)
{
static int stk[mxn], tot; stk[++tot] = t; while (!isRoot(t))
stk[++tot] = t = fat[t]; while (tot)push(stk[tot--]);
} inline void splay(int t)
{
pushdown(t); while (!isRoot(t))
{
int f = fat[t];
int g = fat[f]; if (isRoot(f))
rotate(t);
else
{
int a = f && son[f][] == t;
int b = g && son[g][] == f; if (a == b)
rotate(f), rotate(t);
else
rotate(t), rotate(t);
}
}
} inline void access(int t)
{
int q = t; for (int p = ; t; p = t, t = fat[t])
splay(t), son[t][] = p, update(t); splay(q);
} inline void makeRoot(int t)
{
access(t), rev[t] ^= ;
} inline void link(int t, int f)
{
makeRoot(t), fat[t] = f;
} inline void cut(int t)
{
access(t);
fat[son[t][]] = ;
son[t][] = ;
update(t);
} inline int find(int t)
{
access(t); int p = t; while (son[p][])
p = son[p][]; return p;
} inline void Link(int t, int f)
{
if (t == f)
{
tag[t] = f;
return;
} if (find(t) != find(f))
link(t, f);
else
makeRoot(t), tag[t] = f;
} inline void change(int t, int f)
{
access(t); int p = find(t); if (!tag[p])
cut(t), Link(t, f);
else
{
if (t == p)
{
tag[p] = ;
Link(t, f);
}
else
{
int k = tag[p]; cut(t), Link(t, f); if (find(k) != find(p))
link(p, k), tag[p] = ;
}
}
} int n, m, s[mxn]; signed main(void)
{
scanf("%d%d", &n, &m); for (int i = ; i <= n; ++i)
scanf("%d", s + i); for (int i = ; i <= n; ++i)
{
int t = i + s[i]; if (t < )
Link(i, n + );
else if (t > n)
Link(i, n + );
else
Link(i, t);
} for (int i = ; i <= m; ++i)
{
int opt; scanf("%d", &opt); if (opt == )
{
int t; scanf("%d", &t); int p = find(t); if (tag[p])
puts("-1");
else
{
makeRoot(n + ), access(t);
printf("%d\n", siz[son[t][]]);
}
}
else
{
int a, b; scanf("%d%d", &a, &b); s[a] = b; int t = a + b; if (t < )
change(a, n + );
else if (t > n)
change(a, n + );
else
change(a, t);
}
}
}

@Author: YouSiki

BZOJ 4764: 弹飞大爷的更多相关文章

  1. BZOJ 4764: 弹飞大爷 LCT

    思路并不难,主要是细节需要注意一下. 在 lct 中,删边要写成:f[lson]=0,lson=0 (因为删 x->y 时 y 不一定是左儿子,y 只是 x 的前驱) 然后 f[lson]=ls ...

  2. 【BZOJ】4764: 弹飞大爷 LCT

    [题意]给定n个数字ai,表示大爷落到i处会被弹飞到i+ai处,弹飞到>n或<1处则落地.m次操作,修改一个ai,或询问大爷落到x处经过几次落地(或-1).n,m<=10^5,|ai ...

  3. 【LCT维护基环内向树森林】BZOJ4764 弹飞大爷

    4764: 弹飞大爷 Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 101  Solved: 52[Submit][Status][Discuss] ...

  4. 【BZOJ4764】弹飞大爷 LCT

    [BZOJ4764]弹飞大爷 Description 自从WC退役以来,大爷是越来越懒惰了.为了帮助他活动筋骨,也是受到了弹飞绵羊一题的启发,机房的小伙伴们决定齐心合力构造一个下面这样的序列.这个序列 ...

  5. 【bzoj 4764】弹飞大爷

    Description 自从WC退役以来,大爷是越来越懒惰了.为了帮助他活动筋骨,也是受到了弹飞绵羊一题的启发,机房的小伙伴们决定齐心合力构造一个下面这样的序列.这个序列共有N项,每项都代表了一个小伙 ...

  6. BZOJ4764弹飞大爷——LCT

    题目描述 自从WC退役以来,大爷是越来越懒惰了.为了帮助他活动筋骨,也是受到了弹飞绵羊一题的启发,机房的小伙伴们 决定齐心合力构造一个下面这样的序列.这个序列共有N项,每项都代表了一个小伙伴的力量值, ...

  7. bzoj4764: 弹飞大爷

    Description 自从WC退役以来,大爷是越来越懒惰了.为了帮助他活动筋骨,也是受到了弹飞绵羊一题的启发,机房的小伙伴们 决定齐心合力构造一个下面这样的序列.这个序列共有N项,每项都代表了一个小 ...

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

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

  9. bzoj 2002: 弹飞绵羊 Link-Cut-Tree

    题目: Description 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置, ...

随机推荐

  1. Linux下端口被占用确认

    有时候关闭软件后,后台进程死掉,导致端口被占用.下面以JBoss端口8083被占用为例,列出详细解决过程. 解决方法: 1.查找被占用的端口 netstat -tln netstat -tln | g ...

  2. Docker中查看Mysql数据库中的各环境参数

    通过官方的文档可以看到运行MySQL容器的命令是: docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=mypwd -d mysql:tag 如:d ...

  3. Codeforces Round #503 Div1+Div2 1019&1020

    https://winniechen.cn/?p=188 这个还是直接放链接吧,毕竟内容比较多...

  4. [Oracle]坏块处理:确认坏块的对象

    如果已经知道 FILE#,BLOCK#,则 可以通过如下查询来看: SQL> SELECT SEGMENT_TYPE,OWNER||'.'||SEGMENT_NAME FROM DBA_EXTE ...

  5. 【干货】YUM安装PHP 7版本后,增加phalcon框架的报错解决

    目录 1.yum安装php 7.x版本,此处部署7.3版本 2.安装phalcon框架 2.1.PHP版本依赖关系 2.2.编译phalcon扩展模块 2.3.增加扩展文件 3.部署phalcon遇到 ...

  6. libgdx学习记录12——圆角矩形CircleRect

    libgdx提供了ShapeRenderer这个工具,用它可以画点.画线.画圆.画矩形.画椭圆.画扇形,但是没有提供画圆角矩形的方法. 刚开始自己尝试分成8端,4端画直线,4端画扇形,发现多了半径几部 ...

  7. Panorama——H5实现全景图片原理

    前言 H5是怎么实现全景图片播放呢? 正文 全景图的基本原理即 "等距圆柱投影",这是一种将球体上的各个点投影到圆柱体的侧面上的一种投影方式,投影后再展开就是一张 2:1 的矩形图 ...

  8. 9、Dockerfile实战-Nginx

    上一节我们详解Dockerfile之后,现在来进行实战.我们通过docker build来进行镜像制作. build有如下选项: [root@localhost ~a]# docker build - ...

  9. git 创建标签和删除标签

    创建标签 在Git中打标签非常简单,首先,切换到需要打标签的分支上: $ git branch * dev master $ git checkout master Switched to branc ...

  10. 基于约束的SQL攻击

    前言 值得庆幸的是如今开发者在构建网站时,已经开始注重安全问题了.绝大部分开发者都意识到SQL注入漏洞的存在,在本文我想与读者共同去探讨另一种与SQL数据库相关的漏洞,其危害与SQL注入不相上下,但却 ...