[BZOJ 2002] [HNOI2010]弹飞绵羊(Link Cut Tree)
[BZOJ 2002] [HNOI2010]弹飞绵羊(Link Cut Tree)
题面
某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏。游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹ki步,达到第i+ki个装置,若不存在第i+ki个装置,则绵羊被弹飞。绵羊想知道当它从第i个装置起步时,被弹几次后会被弹飞。为了使得游戏更有趣,Lostmonkey可以修改某个弹力装置的弹力系数,任何时候弹力系数均为正整数。
分析
首先把所有点编号+1,建立虚拟节点n+1表示被弹飞。如果i+ki>n就连边(i,n+1)否则连边(i,i+ki)。
修改就是先删边再加边
查询其实就是查询x到n+1的路径长度.split(x,n+1)后的子树大小-1即为答案
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 200000
using namespace std;
struct link_cut_tree{
#define lson(x) (tree[x].ch[0])
#define rson(x) (tree[x].ch[1])
#define fa(x) (tree[x].fa)
struct node{
int ch[2];
int fa;
int sz;
int revm;
}tree[maxn+5];
inline bool is_root(int x){
return !(lson(fa(x))==x||rson(fa(x))==x);
}
inline int check(int x){
return rson(fa(x))==x;
}
void push_up(int x){
tree[x].sz=tree[lson(x)].sz+tree[rson(x)].sz+1;
}
void reverse(int x){
swap(lson(x),rson(x));
tree[x].revm^=1;
}
void push_down(int x){
if(tree[x].revm){
reverse(lson(x));
reverse(rson(x));
tree[x].revm=0;
}
}
void push_down_all(int x){
if(!is_root(x)) push_down_all(fa(x));
push_down(x);
}
void rotate(int x){
int y=fa(x),z=fa(y),k=check(x),w=tree[x].ch[k^1];
tree[y].ch[k]=w;
tree[w].fa=y;
if(!is_root(y)) tree[z].ch[check(y)]=x;
tree[x].fa=z;
tree[x].ch[k^1]=y;
tree[y].fa=x;
push_up(y);
push_up(x);
}
void splay(int x){
push_down_all(x);
while(!is_root(x)){
int y=fa(x);
if(!is_root(y)){
if(check(x)==check(y)) rotate(y);
else rotate(x);
}
rotate(x);
}
push_up(x);
}
void access(int x){
for(int y=0;x;y=x,x=fa(x)){
splay(x);
rson(x)=y;
push_up(x);
}
}
void make_root(int x){
access(x);
splay(x);
reverse(x);
}
void split(int x,int y){
make_root(x);
access(y);
splay(y);
}
void link(int x,int y){
make_root(x);
fa(x)=y;
}
void cut(int x,int y){
split(x,y);
lson(y)=fa(x)=0;
push_up(y);
}
int query(int x,int y){//查询x到y的路径长度,即split出来的子树大小-1
split(x,y);
return tree[y].sz-1;
}
}T;
int n,m;
int a[maxn+5];
//虚拟节点n+1表示被弹飞
inline int get_nex(int x,int k){//找到被弹到的节点
if(x+k<=n) return x+k;
else return n+1;
}
int main(){
int cmd,x,k;
scanf("%d",&n);
for(int i=1;i<=n+1;i++) T.tree[i].sz=1;
// T.link(4,5);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
T.link(i,get_nex(i,a[i]));
}
scanf("%d",&m);
for(int i=1;i<=m;i++){
scanf("%d",&cmd);
if(cmd==1){
scanf("%d",&x);
x++;
printf("%d\n",T.query(x,n+1));//查询x到n+1路径长度
}else{
scanf("%d %d",&x,&k);
x++;
T.cut(x,get_nex(x,a[x]));
a[x]=k;
T.link(x,get_nex(x,a[x]));
}
}
}
[BZOJ 2002] [HNOI2010]弹飞绵羊(Link Cut Tree)的更多相关文章
- bzoj 2002 Bounce 弹飞绵羊
bzoj 2002 Bounce 弹飞绵羊 设一个虚拟节点表示被弹飞,则每个点的后继点是唯一确定的,每个点向它的后继点连边,就形成了一颗树. 询问就是问某个节点到虚拟节点的路径长度,修改就删除原来向后 ...
- BZOJ 2002 Bounce 弹飞绵羊 (分块或动态树)
2002: [Hnoi2010]Bounce 弹飞绵羊 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 13768 Solved: 6989[Subm ...
- BZOJ 2002 Bounce 弹飞绵羊 —— 分块算法
题目链接:https://vjudge.net/problem/HYSBZ-2002 2002: [Hnoi2010]Bounce 弹飞绵羊 Time Limit: 10 Sec Memory Li ...
- bzoj 2002 Bounce 弹飞绵羊(分块)
2002: [Hnoi2010]Bounce 弹飞绵羊 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 11202 Solved: 5698[Subm ...
- 【bzoj 2002】弹飞绵羊
Description 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置 ...
- 2002. [HNOI2010]弹飞绵羊【LCT】
Description 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置 ...
- BZOJ.2002.Bounce 弹飞绵羊(LCT)
题目链接 从一个点只能往后跳,即后继状态只有一个,那么拿nxt[x]做fa[x]啊!这样就成了一棵树,从每个点开始的答案是它到所在树的根节点的距离. nxt[]的更改即动态修改树边,用LCT即可. 这 ...
- BZOJ 2002 HNOI2010 弹飞羊 块
标题效果,LCT解释版本:见 http://blog.csdn.net/popoqqq/article/details/38849471 如今,用一只手滑动块,并再次改写这个问题0.0 块短啊 将进入 ...
- P3203 [HNOI2010]弹飞绵羊(LCT)
P3203 [HNOI2010]弹飞绵羊 LCT板子 用一个$p[i]$数组维护每个点指向的下个点. 每次修改时cut*1+link*1就解决了 被弹出界时新设一个点,权为0,作为终点表示出界点.其他 ...
随机推荐
- Java当中的集合框架Map
简书作者:达叔小生 Java当中的集合框架Map 01 Map提供了三个集合视图: 键集 值集 键-值 映射集 public String getWeek(int num){ if(num<0 ...
- vue子路由设置、全局组件、局部组件的原生写法
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Dell PowerEdge服务器RAID卡驱动下载
Dell PowerEdge服务器RAID卡驱动下载 DELL新阵列卡驱动下载 型号 支持系统驱动 H310/710 /710P/810 Win2008 x32 Windows 2008 x64 Wi ...
- $message的问题
项目中出现$message的问题: 拉取数据成功后 this.$message.success("数据拉取成功")点击拉取第一次不出现,但是代码执行了,后来多次点击就出现了 原因: ...
- 回调函数(callback) python / c++ 演示
什么是回调函数? 我们绕点远路来回答这个问题. 编程分为两类:系统编程(system programming)和应用编程(application programming).所谓系统编程,简单来说,就是 ...
- centos调整屏幕亮度
笔记本安装centos6.5后亮度无法通过键盘快捷键调节,可以通过安装软件来调节. 安装:yum install xgamma 设置亮度:xgamma -gamma n( 0.1 < n < ...
- PM2工作原理
PM2工作原理 要理解pm2就要理解god和santan的关系,god和santan的关系就相当于盖娅和黑底斯在pm2中的01世界中,每一行代码每一个字节都安静的工作god就是Daemon进程 守护进 ...
- venv转向pipenv
先编译安装你需要的Python版本:参考https://www.cnblogs.com/zxpo/p/10011871.html python3.6安装在:/usr/bin/python3.6目录下: ...
- oc中枚举映射字符串技巧
后台返枚举数据给app,app需要对不同枚举转换成字符串显示. 一般想到方法用 switch 根据不同枚举变量返回不同字符串,结果就是判断代码写得很长,不优雅.更简便方式有如下: typedef NS ...
- JS编程规范
在第一家公司用C++时,公司有着严格的代码规范,甚至到了严苛的地步,现在回想起来,对它充满感激.一个好的习惯让你收益终身. 之后使用JS/TS却没有为自己定一套编程规范,所幸为时不晚,在这里参考air ...