bzoj 2002: [Hnoi2010]Bounce 弹飞绵羊
2016-02-15 10:32
351 查看
Submit: 6521 Solved: 3420
[Submit][Status][Discuss]
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
41 2 1 1
3
1 1
2 1 1
1 1
Sample Output
23 题解: 如果绵羊能从i跳到j,则连一条由i连向j的边,如果能被弹飞,连向n+1,连完之后会形成一个树结构。 由于可以更改弹力系数,所以树边之间存在断开和连接的操作,就是用动态树来完成。
#include<iostream> #include<cstdlib> #include<cstdio> #include<cmath> #include<algorithm> #include<queue> #include<vector> using namespace std; const int N=200005; inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int n,m; int next ,c [2],fa ,size ,st ; bool rev ; bool isroot(int x){ return x!=c[fa[x]][0]&&x!=c[fa[x]][1]; } void pushup(int x){ size[x]=size[c[x][0]]+size[c[x][1]]+1; } void pushdown(int x){ int l=c[x][0],r=c[x][1]; if(rev[x]==true){ rev[x]^=1; rev[l]^=1; rev[r]^=1; swap(c[x][0],c[x][1]); } } void rotate(int x){ int y=fa[x],z=fa[y],l,r; if(x==c[y][0]) l=0;else l=1; r=l^1; if(!isroot(y)){ if(y==c[z][0]) c[z][0]=x; else c[z][1]=x; } fa[x]=z; fa[y]=x; fa[c[x][r]]=y; c[y][l]=c[x][r]; c[x][r]=y; pushup(y); pushdown(x); } void splay(int x){ int top=0; st[++top]=x; for(int i=x;isroot(i)==false;i=fa[i]){ st[++top]=fa[i]; } for(int i=top;i;i--) pushdown(st[i]); while(!isroot(x)){ int y=fa[x],z=fa[y]; if(!isroot(y)){ if((x==c[y][0]&&y==c[z][0])||(x==c[y][1]&&y==c[z][1])){ rotate(y),rotate(x); } else rotate(x),rotate(x); } else rotate(x); } } void access(int x){ int t=0; while(x!=0){ splay(x); c[x][1]=t; t=x; x=fa[x]; } } void rever(int x){ access(x); splay(x); rev[x]^=1; } void cut(int x,int y){ rever(x); access(y); splay(y); c[y][0]=fa[x]=0; } void link(int x,int y){ rever(x); fa[x]=y; splay(x); } int main(){ n=read(); for(int i=1;i<=n;i++){ int x=read(); fa[i]=x+i; size[i]=1; if(fa[i]>n+1) fa[i]=n+1; next[i]=fa[i]; } size[n+1]=1; m=read(); for(int i=1;i<=m;i++){ int f=read(); if(f==1){ rever(n+1); int x=read(); x++; access(x); splay(x); printf("%d\n",size[c[x][0]]); } else{ int x=read(),y=read(); x++; int t=min(n+1,x+y); cut(x,next[x]); link(x,t); next[x]=t; } } return 0; }
相关文章推荐
- iOS音频处理
- 全面复习之SQL(9)-oracle多表查询,连接查询
- web后台开发入门了解
- quartz spring 实现动态定时任务
- LeetCode -- Min Stack
- 【JSTL】--读取实体成员变量吗?--drp212
- Linux学习笔记:ls命令
- 【转载】为什么无线信号(RSSI)是负值
- Android Studio获取SHA1(获取SHA1的通用方法)
- [solr] - spell check
- 有用的blog
- Linux do some cool things or funny things
- C# socket nat 映射 网络 代理 转发
- [solr] - Facet - autocomplete
- Core Image 和视频
- python模块--random
- oracle14连接NL Exception was generated异常问题
- 自动删除Mysql备份(数组+for)
- 基于python yield机制的异步操作同步化编程模型
- 学习新东西的唯一方法