BZOJ2002 Hnoi2010 Bounce 弹飞绵羊


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

Sample Input

4

1 2 1 1

3

1 1

2 1 1

1 1

Sample Output

2

3


分块做法和LCT做法都有

先讲讲LCT,就是一个板子,把当前点和可以连到的点连边,然后修改弹力值就是把边断开然后重新连一条边,维护的答案是一条链的长度,在这里可以直接用LCT的性质直接维护siz

#include<bits/stdc++.h>
using namespace std;
#define N 200010
#define INF 1e9
inline int read(){
int res=0,w=1;char c=getchar();
while(!isdigit(c)&&c!='-')c=getchar();
if(c=='-')w=-1,c=getchar();
while(isdigit(c))res=(res<<1)+(res<<3)+c-'0',c=getchar();
return res;
}
struct Link_Cut_Tree{
int fa[N],son[N][2],siz[N];bool rev[N];
Link_Cut_Tree(){memset(rev,0,sizeof(rev));}
bool isroot(int t){return son[fa[t]][0]!=t&&son[fa[t]][1]!=t;}
bool Son(int t){return son[fa[t]][1]==t;}
void pushup(int t){siz[t]=siz[son[t][0]]+siz[son[t][1]]+1;}
void pushdown(int t){
if(!isroot(t))pushdown(fa[t]);
if(rev[t]){
rev[t]^=1;
rev[son[t][0]]^=1;
rev[son[t][1]]^=1;
swap(son[t][0],son[t][1]);
}
}
void rotate(int t){
int f=fa[t],g=fa[f];
bool a=Son(t),b=a^1;
if(!isroot(f))son[g][Son(f)]=t;fa[t]=g;
son[f][a]=son[t][b];fa[son[t][b]]=f;
son[t][b]=f;fa[f]=t;
pushup(f);pushup(t);
}
void splay(int t){
pushdown(t);
while(!isroot(t)){
int f=fa[t];
if(!isroot(f)){
if(Son(t)^Son(f))rotate(t);
else rotate(f);
}
rotate(t);
}
}
void access(int t){
int tmp=0;
while(t){
splay(t);
son[t][1]=tmp;
if(tmp)fa[tmp]=t;pushup(t);
tmp=t;t=fa[t];
}
}
void putroot(int t){
access(t);
splay(t);
rev[t]^=1;
}
void link(int x,int y){putroot(x);fa[x]=y;}
void cut(int x,int y){
putroot(x);
access(y);
splay(y);
son[y][0]=fa[x]=0;
pushup(y);
}
int query(int x,int y){
putroot(y);
access(x);
splay(x);
return siz[x]-1;
}
}lct;
int n,m,a[N];
int main(){
n=read();
for(int i=1;i<=n;i++)a[i]=read();
for(int i=1;i<=n;i++)
lct.link(i,(i+a[i]>n)?n+1:i+a[i]);
m=read();
for(int i=1;i<=m;i++){
int op,x,y;
scanf("%d",&op);
if(op==1){
scanf("%d",&x);x++;
printf("%d\n",lct.query(x,n+1));
}else{
scanf("%d%d",&x,&y);x++;
lct.cut(x,(x+a[x]>n)?n+1:x+a[x]);
a[x]=y;
lct.link(x,(x+a[x]>n)?n+1:x+a[x]);
}
}
return 0;
}

然后讲讲分块,每次暴力跳,维护一下每个点跳出当前块的操作次数,暴力修改暴力查询就好了

#include<bits/stdc++.h>
using namespace std;
#define INF 0x7fffffff
#define LL long long
#define N 1000010
const int siz=1000;
struct Temp{int to,tmp,bel;}a[N];
int n,m,pre[N];
int read(){
int ans=0,w=1;char c=getchar();
while(!isdigit(c)&&c!='-')c=getchar();
if(c=='-')c=getchar(),w=-1;
while(isdigit(c))ans=ans*10+c-'0',c=getchar();
return ans*w;
}
void modify(int x){
if(a[x+pre[x]].bel!=a[x].bel){
a[x].to=x+pre[x];
a[x].tmp=1;
}else{
a[x].to=a[x+pre[x]].to;
a[x].tmp=a[x+pre[x]].tmp+1;
}
return;
}
void build(){
for(int i=1;i<=n;i++)a[i].bel=(i-1)/siz+1;
for(int i=n;i>=1;i--)
if(i+pre[i]>n)a[i].tmp=1,a[i].to=0;
else modify(i);
}
int query(int x){
int ans=0;
while(x){
ans+=a[x].tmp;
x=a[x].to;
}
return ans;
}
int main(){
n=read();
for(int i=1;i<=n;i++)pre[i]=read();
build();
m=read();
for(int i=1;i<=m;i++){
int op=read(),x;
if(op==1){
x=read()+1;
printf("%d\n",query(x));
}else{
x=read()+1,pre[x]=read();
int fro=(a[x].bel-1)*siz+1;
for(int i=x;i>=fro;i--)modify(i);
}
}
return 0;
}

BZOJ2002 Hnoi2010 Bounce 弹飞绵羊 【LCT】【分块】的更多相关文章

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

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

  2. bzoj2002 [Hnoi2010]Bounce 弹飞绵羊【分块】

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2002 这一题除了LCT解法,还有一种更巧妙,代码量更少的解法,就是分块.先想,如果仅仅记录每 ...

  3. [BZOJ2002][Hnoi2010]Bounce弹飞绵羊 LCT

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2002 建图,每次往后面跳就往目标位置连边,将跳出界的点设为同一个点.对于修改操作发现可以用 ...

  4. BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊 【分块】

    任意门:https://www.lydsy.com/JudgeOnline/problem.php?id=2002 2002: [Hnoi2010]Bounce 弹飞绵羊 Time Limit: 10 ...

  5. 2002: [Hnoi2010]Bounce 弹飞绵羊(分块)

    2002: [Hnoi2010]Bounce 弹飞绵羊 时间限制: 10 Sec  内存限制: 259 MB 题目描述 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他 ...

  6. BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊 LCT

    2002: [Hnoi2010]Bounce 弹飞绵羊 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOn ...

  7. [bzoj2002][Hnoi2010]Bounce弹飞绵羊_LCT

    Bounce弹飞绵羊 bzoj-2002 Hnoi-2010 题目大意:n个格子,每一个格子有一个弹簧,第i个格子会将经过的绵羊往后弹k[i]个,达到i+k[i].如果i+k[i]不存在,就表示这只绵 ...

  8. bzoj2002: [Hnoi2010]Bounce 弹飞绵羊 [分块][LCT]

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

  9. [bzoj2002][Hnoi2010]Bounce弹飞绵羊——分块

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

随机推荐

  1. ThinkPHP的URL重写时遇到No input file specified的解决方法

    因为在Fastcgi模式下,php不支持rewrite的目标网址的PATH_INFO的解析 ThinkPHP运行在URL_MODEL=2时,会出现 No input file specified.的情 ...

  2. Lucene 初步 之 HelloWorld

    万恶的源头 HelloWorld 要完成lucene 的配置 需要几个jar包 (如果需要可以留言我私发) 创建索引API分析: 1. Directory: 类代表一个Lucene索引的位置,FSDi ...

  3. ubuntu18.04里更新系统源和pip源

    一.修改ubuntu系统源 我的ubuntu系统是在清华的开源网站上下的,所以我还以为他应该就帮我弄好源了,可是没想到下载的还是非常慢,看到下载的时候网址前还有个us,就知道不是国内源了.所以这里我们 ...

  4. Nordic nRF5 SDK和softdevice介绍

    SDK和Softdevice的区别是什么?怎么选择SDK和softdevice版本?芯片,SDK和softdevice有没有版本兼容问题?怎么理解SDK目录结构?SDK帮助文档在哪里?Softdevi ...

  5. Java新建线程的3种方法

    Java新建线程的3种方法 =================== Java创建线程有3种方法:(1)继承Thread;(2)实现Runnable接口:(3)实现Callable接口; 由于Java只 ...

  6. jmeter-03 JMeter + Jenkins 集成

    一.准备JMeter 测试计划 mock_api.jmx 接口准备:http://10.1.102.75:8000/mock/api/jmeter 二.jenkins 插件准备  Performanc ...

  7. 1-25-循环控制符break、continue和函数详解

    大纲: 1-for循环补充 1-1-for循环实战---类C格式应用 2-break.continue循环控制符 2-1实战:帮助理解break.continue作用 3-函数详解 3-1.脚本文件中 ...

  8. 玲珑oj 1117 线段树+离线+离散化,laz大法

    1117 - RE:从零开始的异世界生活 Time Limit:1s Memory Limit:256MByte Submissions:438Solved:68 DESCRIPTION 486到了异 ...

  9. hdu 4679 Terrorist’s destroy 树的直径+dp

    题意:给你一棵树,每条边都有值W,然后问你去掉一条边,令val = w*max(两颗新树的直径),求val最小值~ 做法,先求树的直径,然后算出直径上每个点的最长枝条长度.这样对于每一条边,假如是枝条 ...

  10. pip 使用总结

    pip的安装: Windows Python2.7 以上的版本均自带pip,安装的时候记得勾选对应的选项即可. 安装easy_install, 通过easy_install pip 下载[easy_s ...