刷题总结——弹飞绵羊(bzoj2002)
题目:
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
1 2 1 1
3
1 1
2 1 1
1 1
Sample Output
3
题解:
算法1:引用洛谷官网题解:
LCT裸题。
首先,建立一个虚拟节点n+1n+1,绵羊到达这个节点即被弹飞。
对于每个装置,
如果i+Ki<=ni+Ki<=n,则执行Link(i,i+Ki)Link(i,i+Ki),否则Link(i,n+1)Link(i,n+1)。
对于修改操作,先执行Cut(j,j+Kj)Cut(j,j+Kj)(如果j+Kj>nj+Kj>n则为n+1n+1),再执行Link(j,j+k)Link(j,j+k)(如果j+k>nj+k>n则为n+1n+1),
并把KjKj赋为kk。
对于询问操作,分别执行MakeRoot(y)MakeRoot(y),Access(n+1)Access(n+1)和Splay(n+1)Splay(n+1),最终答案即为size[n+1]-1size[n+1]−1。
其中size[i]size[i]表示平衡树中节点ii的子树的大小。
表示第一次做的时候智障了····忘记拿n+1作为整棵树的根节点从而不知道怎么求深度···哎··
另外注意update
算法2:分块算法
这道题用分块算法简单得多···而且时间还要快一点
先分块,用pos[i]维护i会跳到块外的哪一点上,用times[i]维护i跳到块外的对应点上需要多少步,每次询问的时候一边跳pos[i]一边往ans加time[i]就可以了,复杂度为√n
对于修改直接修改这个点到所在块的初始点内的pos和time,复杂度同样为√n;
代码:
1.LCT
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<cctype>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
const int N=2e5+;
int tag[N],father[N],size[N],son[N][],stack[N],cnt,to[N];
int n,m,a,b,c;
inline int R()
{
char c;int f=;
for(c=getchar();c<''||c>'';c=getchar());
for(;c<=''&&c>='';c=getchar())
f=(f<<)+(f<<)+c-'';
return f;
}
inline void update(int now)
{
if(now)
{
size[now]=;
if(son[now][]) size[now]+=size[son[now][]];
if(son[now][]) size[now]+=size[son[now][]];
}
}
inline int get(int now)
{
return son[father[now]][]==now;
}
inline void pushdown(int now)
{
if(tag[now]&&now)
{
swap(son[now][],son[now][]);
tag[son[now][]]^=;
tag[son[now][]]^=;
tag[now]=;
}
}
inline bool isroot(int now)
{
if(!father[now]) return true;
else if(son[father[now]][]!=now&&son[father[now]][]!=now) return true;
else return false;
}
inline void rotate(int now)
{
pushdown(father[now]),pushdown(now);
int fa=father[now],ofa=father[fa],which=get(now);
if(!isroot(fa)&&ofa) son[ofa][son[ofa][]==fa]=now;
son[fa][which]=son[now][which^],father[son[fa][which]]=fa;
son[now][which^]=fa,father[fa]=now,father[now]=ofa;
update(fa),update(now);
}
inline void splay(int now)
{
stack[cnt=]=now;
for(int i=now;!isroot(i);i=father[i])
stack[++cnt]=father[i];
for(int i=cnt;i>=;i--)
pushdown(stack[i]);
while(!isroot(now))
{
if(!isroot(father[now]))
rotate(get(father[now])==get(now)?father[now]:now);
rotate(now);
}
}
inline void access(int now)
{
int temp=;
for(;now;temp=now,now=father[now])
{
splay(now),son[now][]=temp;
update(now);
}
}
inline void makeroot(int now)
{
access(now);splay(now);tag[now]^=;
}
inline void link(int a,int b)
{
makeroot(a);father[a]=b;
}
inline void cut(int a,int b)
{
makeroot(a);access(b);splay(b);
father[a]=son[b][]=;
}
inline int getans(int now)
{
makeroot(now);
access(n+);splay(n+);
return size[n+]-;
}
int main()
{
//freopen("a.in","r",stdin);
//freopen("a.out","w",stdout);
n=R();
for(int i=;i<=n+;i++)
size[i]=;
for(int i=;i<=n;i++)
{
a=R();
if(a+i<=n&&a!=)
{
to[i]=i+a;
link(i,a+i);
}
else if(a+i>n&&a!=)
{
to[i]=n+;
link(i,n+);
}
}
m=R();
while(m--)
{
a=R(),b=R();
if(a==)
{
int ans=getans(b+);
printf("%d\n",ans);
}
else
{
c=R();cut(b+,to[b+]);
if(b++c<=n&&c!=)
to[b+]=b++c,link(b+,b++c);
else if(b++c>n&&c!=)
to[b+]=n+,link(b+,n+);
}
}
return ;
}
2.分块
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<cctype>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
const int N=2e5+;
int n,m,times[N],pos[N],a[N],Right[N],Left[N],id[N],s,tots;
inline int R()
{
char c;int f=;
for(c=getchar();c<''||c>'';c=getchar());
for(;c<=''&&c>='';c=getchar())
f=(f<<)+(f<<)+c-'';
return f;
}
int main()
{
//freopen("a.in","r",stdin);
n=R();s=(int)sqrt(n);
for(int i=;i<=n;i++)
{
if(i%s==) id[i]=tots,Right[tots]=i;
else if(i%s==) id[i]=++tots,Left[tots]=i;
else id[i]=tots;
}
for(int i=;i<=n;i++) a[i]=R();
for(int i=n;i>=;i--)
{
int temp=a[i]+i;
if(temp>=n+)
pos[i]=-,times[i]=;
else if(temp<=Right[id[i]])
pos[i]=pos[temp],times[i]=times[temp]+;
else
pos[i]=temp,times[i]=;
}
m=R();int q,x,y;
while(m--)
{
q=R();
if(q==)
{
x=R();int ans=;
for(int i=x+;i!=-;i=pos[i])
ans+=times[i];
printf("%d\n",ans);
}
else
{
x=R(),y=R();
a[x+]=y;
for(int i=x+;i>=Left[id[x]];i--)
{
int temp=i+a[i];
if(temp>=n+) pos[i]=-,times[i]=;
else if(temp<=Right[id[i]])
pos[i]=pos[temp],times[i]=times[temp]+;
else
pos[i]=temp,times[i]=;
}
}
}
return ;
}
刷题总结——弹飞绵羊(bzoj2002)的更多相关文章
- 洛谷 P3203 [HNOI2010]弹飞绵羊 || bzoj2002
看来这个lct板子的确没什么问题 好像还可以分块做 #include<cstdio> #include<algorithm> using namespace std; type ...
- [bzoj2002][Hnoi2010]Bounce弹飞绵羊_LCT
Bounce弹飞绵羊 bzoj-2002 Hnoi-2010 题目大意:n个格子,每一个格子有一个弹簧,第i个格子会将经过的绵羊往后弹k[i]个,达到i+k[i].如果i+k[i]不存在,就表示这只绵 ...
- 【BZOJ2002】弹飞绵羊(Link-Cut Tree)
[BZOJ2002]弹飞绵羊(Link-Cut Tree) 题面 题目描述 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始,Lost ...
- 【BZOJ2002】 [Hnoi2010]Bounce 弹飞绵羊
BZOJ2002 [Hnoi2010]Bounce 弹飞绵羊 Solution 很早以前写的一道分块题,最近在搞LCT,又做了一遍. 1.LCT做法 看到这种动态修改,想下LCT怎么维护. 修改操作就 ...
- 【bzoj2002】[Hnoi2010]Bounce 弹飞绵羊 分块
[bzoj2002][Hnoi2010]Bounce 弹飞绵羊 2014年7月30日8101 Description 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀 ...
- BZOJ2002 Hnoi2010 Bounce 弹飞绵羊 【LCT】【分块】
BZOJ2002 Hnoi2010 Bounce 弹飞绵羊 Description 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始, ...
- 【codevs2333】&【BZOJ2002】弹飞绵羊[HNOI2010](分块)
我其实是在codevs上看到它的题号后才去做这道题的...2333... 题目传送门:codevs:http://codevs.cn/problem/2333/ bzoj:http://www.lyd ...
- [BZOJ2002][洛谷P3203][Hnoi2010]Bounce 弹飞绵羊(LCT维护链长)
luogu传送门 2002: [Hnoi2010]Bounce 弹飞绵羊 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 16082 Solved: ...
- 【bzoj2002】[Hnoi2010]Bounce 弹飞绵羊 link-cut-tree
2016-05-30 11:51:59 用一个next数组,记录点x的下一个点是哪个 查询时,moveroot(n+1),access(x),splay(x) ,输出size[ch[x][0]]即为答 ...
随机推荐
- JS 语言基础
两个变量 相加 var s="今天下雨了"; var i=10; alert(i+s); 这里的i+s是拼接的意思 显示出来是 今天下雨了10 假设我改 s="2 ...
- 51nod 1212 无向图最小生成树(Kruskal模版题)
N个点M条边的无向连通图,每条边有一个权值,求该图的最小生成树. Input 第1行:2个数N,M中间用空格分隔,N为点的数量,M为边的数量.(2 <= N <= 1000, 1 &l ...
- Microsoft Sql server2005的安装步骤和常见问题解决方案
一:安装sql server 2005过程中出现 如下问题:“选择的功能中没有任何功能可以安装或升级”: 解决方案:Microsoft SQL Server 2005→配置工具→SQL配置管理器→SQ ...
- python一周速成学习笔记
目录 一:语法元素 1.注释,变量,空格的使用 2.输入函数,输出函数 3.分支语句,循环语句 4.保留字in,同步赋值 5.import与def以及turtle库 6.eval函数与repr函数 二 ...
- Hyperledger Fabric on SAP Cloud Platform
今天的文章来自Wen Aviva, 坐Jerry面对面的程序媛. Jerry在之前的公众号文章<在SAP UI中使用纯JavaScript显示产品主数据的3D模型视图>已经介绍过Aviva ...
- 用Hexo免费搭建你自己的博客
Hexo基于node.js,可用于生成静态博客,结合github和Mac,可以专注创作了. 深入学习见文末引用. hexo安装 brew install node npm install hexo-c ...
- ios 使用NSRegularExpression解析正则表达式
初始化一个 NSRegularExpression 对象 注:_str是要匹配的字符串 NSRegularExpression *regex = [NSRegularExpression regu ...
- python_111_动态导入模块
lib下aa.py文件内容: class C: def __init__(self): self.name='alex' from lib import aa#正常导入 print(aa.C) 动态导 ...
- python之dic {字典}(重要指数*****)
1. 什么是字典 {'name': '汪峰', 'age': 18} '键':'值' 别的语言键值对数据 键: 必须是可哈希(不可变的数据类型),并且是唯一的 值: 任意 可以保存任意类型的数据 字典 ...
- Struts2 执行流程
struts2执行原理(执行流程) 一个请求在Struts2框架中的处理大概分为以下几个步骤: 1 客户端发送请求:(HttpServletRequest)2 这个请求经过一系列的过滤器(Filter ...