bzoj 2002: [Hnoi2010]Bounce 弹飞绵羊
2017-08-03 16:55
274 查看
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<=100000Output
对于每个i=1的情况,你都要输出一个需要的步数,占一行。Sample Input
41 2 1 1
3
1 1
2 1 1
1 1
Sample Output
23
题解:
算是简单的吧,可以用把每个弹簧看作一个点,然后LCT维护连通性即可.
如果i+a[i]>n就将i连向n+1 反之连在i+a[i]上.
修改就是先cut再link
答案就是将n+1旋到根 并且把询问点和n+1放到同一Splay中 , 深度比它小的点的个数为答案,然后显然为左子树大小
但是有个问题:gdb的时候并没有发现reserve的作用...于是发现确实没卵用..只不过修改操作要稍作变化
个人浅薄的理解为:mroot操作只是为了在cut得时候把不相关的连在一起,而这题只是cut与原父亲的连边 所以不必mroot
1RE :rotate都打错好多遍,果然还是巨水
#include <algorithm> #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <cmath> using namespace std; const int N=200005; int ch [2],size ,fa ;bool rev ,rt ; int gi(){ int str=0;char ch=getchar(); while(ch>'9' || ch<'0')ch=getchar(); while(ch>='0' && ch<='9')str=(str<<1)+(str<<3)+ch-48,ch=getchar(); return str; } void updata(int r){ if(!r)return ; swap(ch[r][0],ch[r][1]); rev[r]^=1; } void pushdown(int r){ if(!rev[r])return ; updata(ch[r][0]);updata(ch[r][1]); rev[r]=0; } void upsize(int r){ if(r) size[r]=size[ch[r][1]]+size[ch[r][0]]+1; } void rotate(int r){ int y=fa[r];bool t=(ch[y][1]==r); ch[y][t]=ch[r][!t]; ch[r][!t]=y; fa[ch[y][t]]=y; fa[r]=fa[y]; if(rt[y]) rt[y]=false,rt[r]=true; else ch[fa[y]][ch[fa[y]][1]==y]=r; fa[y]=r; upsize(y);upsize(r); } void Push(int r){ if(!rt[r] && r)Push(fa[r]); pushdown(r); } void splay(int r){ Push(r); while(!rt[r]){ int y=fa[r],yy=fa[y]; if(rt[y]) rotate(r); if((ch[yy][1]==y)==(ch[y][1]==r))rotate(y),rotate(r); else rotate(r),rotate(r); } pushdown(r);upsize(r); } void access(int x){ int y=0; do{ splay(x); rt[ch[x][1]]=true;rt[ch[x][1]=y]=false; upsize(x); x=fa[y=x]; }while(x); } void mroot(int x){ access(x); splay(x); updata(x); } void link(int x,int y){ mroot(x);fa[x]=y;upsize(y); } void cut(int x,int y){ mroot(x);access(y);splay(y); pushdown(y); fa[x]=ch[y][0]=0;rt[x]=true; upsize(y); } int n,m,a ; void query(int x){ mroot(n+1); access(x); splay(x); printf("%d\n",size[ch[x][0]]); } void change(int x,int to){ if(x+a[x]<=n)cut(x,x+a[x]); else cut(x,n+1); a[x]=to; if(x+a[x]<=n)link(x,x+a[x]); else link(x,n+1); } int main() { freopen("bzoj_2002.in","r",stdin); freopen("bzoj_2002.out","w",stdout); int x,y,z; n=gi();rt[0]=true; for(int i=1;i<=n+1;i++)size[i]=1,rt[i]=true; for(int i=1;i<=n;i++){ a[i]=gi(); if(i+a[i]<=n)link(i,i+a[i]); else link(i,n+1); } m=gi(); while(m--){ x=gi();y=gi();y++; if(x==1)query(y); else z=gi(),change(y,z); } return 0; }
相关文章推荐
- bzoj:2002: [Hnoi2010]Bounce 弹飞绵羊
- BZOJ 2002 [Hnoi2010]Bounce 弹飞绵羊 LCT
- bzoj 2002: [Hnoi2010]Bounce 弹飞绵羊
- BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊 动态树
- bzoj 2002: [Hnoi2010]Bounce 弹飞绵羊 LCT
- BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊(分块)
- bzoj 2002: [Hnoi2010]Bounce 弹飞绵羊 lct模板
- 【BZOJ】2002: [Hnoi2010]Bounce 弹飞绵羊(lct)
- [BZOJ 2002][Hnoi2010]Bounce 弹飞绵羊:分块|LCT
- 【LCT】BZOJ2002(Hnoi2010)[Bounce 弹飞绵羊]题解
- [题解]bzoj2002(HNOI2010)Bounce 弹飞绵羊
- 初识lct——洛谷p3203 bzoj2002 [HNOI2010]BOUNCE 弹飞绵羊
- bzoj2002 [Hnoi2010]Bounce 弹飞绵羊【LCT】
- BZOJ 2002 [Hnoi2010]Bounce 弹飞绵羊 (LCT)
- BZOJ2002: [Hnoi2010]Bounce 弹飞绵羊(洛谷P3203)
- BZOJ2002 [Hnoi2010]Bounce 弹飞绵羊
- BZOJ2002: [Hnoi2010]Bounce 弹飞绵羊
- BZOJ 2002 [Hnoi2010]Bounce 弹飞绵羊(分块)
- BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊 分块
- bzoj 2002: [Hnoi2010]Bounce 弹飞绵羊 動態樹