题目描述

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

输入

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

输出

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

样例输入

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

样例输出

3
2
1
2
2
1
-1
-1
-1
3
1
2
3
1
2
 
BZOJ2002的进阶版。
可以发现每个联通块要么是一棵树,要么是一棵内向基环树。
树的话直接像弹飞绵羊那样用LCT维护就行了。
对于基环树我们假设多出的那条边是树根指向另一个点,那么对于这条边我们不连接它,而是存起来。
在删除一条边时如果是基环上的边,那么就可以将之前树根存的那条边连上了。
判断能否弹出直接看当前点是在树中还是基环树中即可。
注意因为这是有向边,所以不能随意改变原树的根。

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<bitset>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define pr pair<int,int>
#define ll long long
using namespace std;
int n,m;
int opt;
int x,y;
int v[200010];
int s[200010][2];
int st[200010];
int f[200010];
int size[200010];
int a[200010];
int is_root(int rt)
{
return rt!=s[f[rt]][0]&&rt!=s[f[rt]][1];
}
int get(int rt)
{
return rt==s[f[rt]][1];
}
void pushup(int rt)
{
size[rt]=size[s[rt][0]]+size[s[rt][1]]+1;
}
void rotate(int rt)
{
int fa=f[rt];
int anc=f[fa];
int k=get(rt);
if(!is_root(fa))
{
s[anc][get(fa)]=rt;
}
s[fa][k]=s[rt][k^1];
f[s[fa][k]]=fa;
s[rt][k^1]=fa;
f[fa]=rt;
f[rt]=anc;
pushup(fa);
pushup(rt);
}
void splay(int rt)
{
for(int fa;!is_root(rt);rotate(rt))
{
if(!is_root(fa=f[rt]))
{
rotate(get(rt)==get(fa)?fa:rt);
}
}
}
void access(int rt)
{
for(int x=0;rt;x=rt,rt=f[rt])
{
splay(rt);
s[rt][1]=x;
pushup(rt);
}
}
int find(int rt)
{
access(rt);
splay(rt);
while(s[rt][0])
{
rt=s[rt][0];
}
splay(rt);
return rt;
}
void link(int x,int y)
{
if(find(y)==x)
{
v[x]=y;
}
else
{
access(x);
splay(x);
f[x]=y;
}
}
void cut(int x,int y)
{
if(v[x]==y)
{
v[x]=0;
}
else
{
int root=find(x);
access(x);
splay(x);
f[s[x][0]]=0;
s[x][0]=0;
pushup(x);
if(v[root]&&find(v[root])!=root)
{
link(root,v[root]);
v[root]=0;
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
size[i]=1;
if(i+a[i]<=n&&i+a[i]>=1)
{
link(i,i+a[i]);
}
}
while(m--)
{
scanf("%d",&opt);
if(opt==1)
{
scanf("%d",&x);
int root=find(x);
if(v[root])
{
printf("-1\n");
}
else
{
access(x);
splay(x);
printf("%d\n",size[x]);
}
}
else
{
scanf("%d%d",&x,&y);
if(x+a[x]<=n&&x+a[x]>=1)
{
cut(x,x+a[x]);
}
a[x]=y;
if(x+a[x]<=n&&x+a[x]>=1)
{
link(x,x+a[x]);
}
}
}
}

BZOJ4764弹飞大爷——LCT的更多相关文章

  1. bzoj4764 弹飞大爷 LCT

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4764 题解 如果 \(a_i > 0\) 的话,那么就是 bzoj2002 的原题.直接 ...

  2. 【BZOJ4764】弹飞大爷 LCT

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

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

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

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

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

  5. bzoj4764: 弹飞大爷

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

  6. BZOJ 4764: 弹飞大爷 LCT

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

  7. bzoj4764: 弹飞大爷 link-cut-tree

    题目传送门 这道题啊 调了一个晚上 因为写的是一个有根树和n个基环的写法 所以写得很奇怪..... 最后发现单独处理树的时候不能随意改变S(就是原来的根)不然size会出错.... #include& ...

  8. BZOJ 4764: 弹飞大爷

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

  9. [BZOJ2002] [Hnoi2010] Bounce 弹飞绵羊 (LCT)

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

随机推荐

  1. battery for stm32

    右边两个1N4148的压降都是0.7V,并且3.3-0.7=2.6V   &   3-0.7=2.3V  可见在电源3.3V正常供电的情况下,电池处于休息状态,这就有效避免了电池的不必要消耗:

  2. ping + traceroute + tracert + tcpdump等命令的原理

    1.ping:关键就在这里,IP层协议通过机器B的IP地址和自己的子网掩码,发现它跟自己属同一网络,就直接在本网络内查找这台机器的. MAC如果以前两机有过通信,在 A 机的 ARP 缓存表应该 有 ...

  3. oracle pls-00382:表达式类型错误

    转载至:pls-00382:表达式类型错误 错误:pls-00382:表达式类型错误 如何产生: 我是在将一个动态sql付给一个nvarchar2变量是出现这个错误的,示例代码如下: declare ...

  4. zookeepeer使用zkCli.sh命令

    一.连接服务器端 [root@sxl132 zookeepeer]# ./bin/zkCli. Connecting to -- ::, [myid:] - INFO [main:Environmen ...

  5. 深入理解 JS 引擎执行机制(同步执行、异步执行以及同步中的异步执行)

    首先明确两点: 1.JS 执行机制是单线程. 2.JS的Event loop是JS的执行机制,深入了解Event loop,就等于深入了解JS引擎的执行. 单线程执行带来什么问题? 在JS执行中都是单 ...

  6. docker for windows 10 添加阿里云镜像仓库无效问题

    原来一直是用cmd来执行docker 命令的,结果今天发现不行了,改了镜像仓库也pull不下来. 后来换用powerShell执行docker pull 才成功.大家可以试试 win+R  运行 po ...

  7. [Spark][Python]DataFrame select 操作例子

    [Spark][Python]DataFrame中取出有限个记录的例子 的 继续 In [4]: peopleDF.select("age")Out[4]: DataFrame[a ...

  8. .NetCore实践篇:成功解决分布式监控ZipKin聚合依赖问题(三)

    前言 读本篇文章之前,可以先读前两篇文章.为了照顾没看过的朋友,我也会稍作复习. 思考大纲: .Net架构篇:思考如何设计一款实用的分布式监控系统? 实践篇一:.NetCore实践篇:分布式监控客户端 ...

  9. 对spring cloud config的一点理解

    以下部分纯属个人理解,但是结果都是经过demo验证. 一.spring cloud config介绍 spring cloud是spring家族中的一个微服务工具包,其中包含了很多微服务的工具.偏向于 ...

  10. 《Linux内核分析》读书笔记(四章)

    <Linux内核分析>读书笔记(四章) 标签(空格分隔): 20135328陈都 第四章 进程调度 调度程序负责决定将哪个进程投入运行,何时运行以及运行多长时间,进程调度程序可看做在可运行 ...