题目大意:有$n$个节点,第$i$个节点有一个弹力系数$k_i$,当到达第$i$个点时,会弹到第$i+k_i$个节点,若没有这个节点($i+k_i>n$)就会被弹飞。有两个操作:

  1. $x:$询问从第$x$个节点开始要多少次会被弹飞
  2. $x,y:$把第$x$个点的弹力系数修改为$y$。

题解:建一个节点标号$n+1$,所有大于$n$的位置都连向这,表示会被弹飞。其他每个节点向会被弹到的节点连边($i->k_i+i$),发现这样会构成一棵树。

询问就是问该点的深度(到$n+1$的距离)。修改就是把原来的边切断,再连上一条新边。可以想到$LCT$,只需要维护每个点到链顶的距离即可。

卡点:1.$get$函数写错

2.在$link$和$cut$操作中换了根,但是在询问中是按照根为$n+1$来做的

C++ Code:

#include <cstdio>
#define maxn 200010
#define lc(rt) son[rt][0]
#define rc(rt) son[rt][1]
using namespace std;
int sz[maxn], son[maxn][2], fa[maxn], tg[maxn];
inline int min(int a, int b) {return a < b ? a : b;}
inline void swap(int &a, int &b) {a ^= b ^= a ^= b;}
inline int get(int rt, int flag = 1) {return son[fa[rt]][flag] == rt;}
inline bool is_root(int rt) {return !(get(rt, 0) || get(rt));}
inline void update(int rt) {sz[rt] = sz[lc(rt)] + sz[rc(rt)] + 1;}
inline void pushdown(int rt) {
tg[rt] ^= 1; tg[lc(rt)] ^= 1; tg[rc(rt)] ^= 1;
swap(lc(rt), rc(rt));
}
inline void rotate(int x) {
int y = fa[x], z = fa[y], b = get(x);
if (!is_root(y)) son[z][get(y)] = x;
fa[son[y][b] = son[x][!b]] = y; son[x][!b] = y;
fa[y] = x, fa[x] = z;
update(y), update(x);
}
int stack[maxn], top;
inline void splay(int x) {
stack[top = 1] = x;
for (int y = x; !is_root(y); stack[++top] = y = fa[y]);
for (; top; top--) if (tg[stack[top]]) pushdown(stack[top]);
for (; !is_root(x); rotate(x)) if (!is_root(fa[x]))
get(x) ^ get(fa[x]) ? rotate(x) : rotate(fa[x]);
update(x);
}
inline void access(int rt) {for (int t = 0; rt; rc(rt) = t, t = rt, rt = fa[rt]) splay(rt);}
inline void make_root(int rt) {access(rt), splay(rt), tg[rt] ^= 1;}
inline void link(int x, int y) {make_root(x), fa[x] = y;}
inline void split(int x, int y) {make_root(x), access(y), splay(y);}
inline void cut(int x, int y) {split(x, y), lc(y) = fa[x] = 0;}
int n, m;
inline int ask(int rt) {
make_root(n + 1);
access(rt);
splay(rt);
return sz[rt] - 1;
}
int s[maxn];
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", &s[i]);
link(i, min(n + 1, i + s[i]));
}
scanf("%d", &m);
for (int i = 0; i < m; i++) {
int op, x, y;
scanf("%d%d", &op, &x); x++;
if (op == 1) printf("%d\n", ask(x));
else {
scanf("%d", &y);
cut(x, min(n + 1, x + s[x]));
s[x] = y;
link(x, min(n + 1, x + y));
}
}
return 0;
}

[洛谷P3203][HNOI2010]弹飞绵羊的更多相关文章

  1. 洛谷 P3203 [HNOI2010]弹飞绵羊 解题报告

    P3203 [HNOI2010]弹飞绵羊 题目描述 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始,Lostmonkey在地上沿着一 ...

  2. 洛谷P3203 [HNOI2010] 弹飞绵羊 [LCT]

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

  3. 洛谷P3203 [HNOI2010]弹飞绵羊(LCT,Splay)

    洛谷题目传送门 关于LCT的问题详见我的LCT总结 思路分析 首先分析一下题意.对于每个弹力装置,有且仅有一个位置可以弹到.把这样的一种关系可以视作边. 然后,每个装置一定会往后弹,这不就代表不存在环 ...

  4. Bzoj2002/洛谷P3203 [HNOI2010]弹飞绵羊(分块)

    题面 Bzoj 洛谷 题解 大力分块,分块大小\(\sqrt n\),对于每一个元素记一下跳多少次能跳到下一个块,以及跳到下一个块的哪个位置,修改的时候时候只需要更新元素所在的那一块即可,然后询问也是 ...

  5. 洛谷 P3203 [HNOI2010]弹飞绵羊 || bzoj2002

    看来这个lct板子的确没什么问题 好像还可以分块做 #include<cstdio> #include<algorithm> using namespace std; type ...

  6. 洛谷 P3203 [HNOI2010]弹飞绵羊 分块

    我们只需将序列分成 n\sqrt{n}n​ 块,对于每一个点维护一个 val[i]val[i]val[i],to[i]to[i]to[i],分别代表该点跳到下一个块所需要的代价以及会跳到的节点编号.在 ...

  7. 洛谷 P3203 [HNOI2010]弹飞绵羊

    题意简述 有n个点,第i个点有一个ki,表示到达i这个点后可以到i + ki这个点 支持修改ki和询问一点走几次能走出所有点两个操作 题解思路 分块, 对于每个点,维护它走到下一块所经过的点数,它走到 ...

  8. [Luogu P3203] [HNOI2010]弹飞绵羊 (LCT维护链的长度)

    题面 传送门:洛谷 Solution 这题其实是有类似模型的. 我们先考虑不修改怎么写.考虑这样做:每个点向它跳到的点连一条边,最后肯定会连成一颗以n+1为根的树(我们拿n+1代表被弹出去了).题目所 ...

  9. P3203 [HNOI2010]弹飞绵羊(LCT)

    P3203 [HNOI2010]弹飞绵羊 LCT板子 用一个$p[i]$数组维护每个点指向的下个点. 每次修改时cut*1+link*1就解决了 被弹出界时新设一个点,权为0,作为终点表示出界点.其他 ...

随机推荐

  1. HTTP-Http状态码301和302的区别

    官方解释: 301 redirect: 301 代表永久性转移(Permanently Moved) 302 redirect: 302 代表暂时性转移(Temporarily Moved ) 共同点 ...

  2. Lavavel5.5源代码 - 限流工具

    app('redis')->connection('default')->throttle('key000') // 每60秒,只能有10个资源被获取,在3秒内获取不到锁抛出异常 -> ...

  3. ARM串口控制终端命令

    配置开发板eth0网络: # ifconfig eth0 10.70.12.168

  4. 11 非阻塞套接字与IO多路复用(进阶)

    1.非阻塞套接字 第一部分 基本IO模型 1.普通套接字实现的服务端的缺陷 一次只能服务一个客户端! 2.普通套接字实现的服务端的瓶颈!!! accept阻塞! 在没有新的套接字来之前,不能处理已经建 ...

  5. pycharm中每次创建py文件时就自动生成代码头,以及出现SyntaxError:Non-ASCII 。。。问题

    我们在pycharm中执行py文件的时候,可能会出现以下错误 这是因为你没有制定编码格式,这时候你需要在文件最开始制定编码格式,代码如下 #!/user/bin/env python #-*- cod ...

  6. unity独立游戏开发日记2018/09/27

    今天优化了下昨天的代码,并且添加了树木和其他资源的生成.还修复了接近石头后,挖掘图标不出现的bug.目前可以在unity中稳定60-70fps. 详看文章:https://www.cnblogs.co ...

  7. P2153 [SDOI2009]晨跑(最小费用最大流)

    题目描述 Elaxia最近迷恋上了空手道,他为自己设定了一套健身计划,比如俯卧撑.仰卧起坐等 等,不过到目前为止,他坚持下来的只有晨跑. 现在给出一张学校附近的地图,这张地图中包含N个十字路口和M条街 ...

  8. WPF中,如何将绑定源设置到单件实例

    原文:WPF中,如何将绑定源设置到单件实例  WPF中,如何将绑定源设置到单件实例                                       周银辉 大概两个月前,曾有位朋友问我:如 ...

  9. 通过transpose和flip实现图像旋转90/180/270度

    在fbc_cv库中,提供了对图像进行任意角度旋转的函数rotate,其实内部也是调用了仿射变换函数warpAffine.如果图像仅是进行90度倍数的旋转,是没有必要用warpAffine函数的.这里通 ...

  10. 不同编译器下,定义一个地址按x字节对齐的数组

    以前一直用MDK,用__align(4)就可以定义一个首地址被4整除.地址按4字节对齐的数组,但今天用IAR发现这么写编译报错. 搜了一下才发现,原来不同的编译器,需要用不同的表达方式: #if de ...