bsoj 3175 【HNOI2010】弹飞绵羊
2016-02-26 20:08
169 查看
Description
Lostmonkey发明了一种超级反弹装置。为了在绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏。游戏一开始,Lostmonkey在地上沿一条直线摆放 n个反弹装置,并按从前往后的方式将反弹装置依次编号为 0 到 n-1,对 0≤i≤n-1,为第 i 个反弹装置设定了初始弹力系数 ki,当绵羊落到第 i 个反弹装置上时,它将被往后弹出 ki 步,即落到第 i+ki 个反弹装置上,若不存在第i+ki个反弹装置,则绵羊被弹飞。
绵羊想知道: 从第i个反弹装置开始, 它被弹出几次 (含被弹飞的那次)后会被弹飞。为使游戏更有趣,Lostmonkey 还可以修改某个反弹装置的弹力系数,但任何时候弹力系数均为正整数。
Input
输入文件第一行是一个整数n,表示地上摆放n个反弹装置,输入文件第二行是用空格隔开的n个正整数k0,k1,…,kn-1,分别表示n个反弹装置的初始弹力系数。
输入文件第三行是一个正整数m,表示后面还有m行输入数据。
接下来的m行,每行至少有用空格隔开的两个整数i和j,若i=1,则你要输出从第j个反弹装置开始,被弹出几次后会被弹飞;若i=2,则该行有用空格隔开的三个整数i,j和k,表示第j个反弹装置的弹力系数被修改为k。
输入的数据保证20%的数据满足n,m≤10000。100%的数据满足n≤200000,m≤100000
Output
输出文件output.txt包含的行数等于输入文件最后m行中i=1的行数。第h行输出一个整数,表示对输入中给出的第h个求弹出次数的问题,基于n个反弹装置当时的弹力系数,求出的弹出次数。
Sample Input
41 2 1 1
3
1 1
2 1 1
1 1
Sample Output
23
我的代码,不知道为什么一直Timeout。:
#include<cstdio> #include<iostream> #include<cmath> #include<algorithm> #include<cstring> using namespace std; struct Link_cut_Tree{ int fa; bool OnPath; int size; int l; int r; int rev; }Tree[2000005]; int n; int next[2000005]; int NEXT(int x,int y){ if(x+y>n)return n+1; else return x+y; } void updata(int x){ Tree[x].size=1; if(Tree[x].l)Tree[x].size+=Tree[Tree[x].l].size; if(Tree[x].r)Tree[x].size+=Tree[Tree[x].r].size;} void pushdown(int x){ if(Tree[x].rev){ swap(Tree[x].l,Tree[x].r); Tree[x].rev=0; Tree[Tree[x].l].rev^=1; Tree[Tree[x].r].rev^=1; } } void Rotate(int x){ int y=Tree[x].fa; int z=Tree[y].fa; if(Tree[y].l==x){ Tree[y].l=Tree[x].r; if(Tree[x].r)Tree[Tree[x].r].fa=y; if(Tree[y].OnPath){ if(Tree[z].l==y)Tree[z].l=x; else Tree[z].r=x; } Tree[x].fa=z; Tree[x].r=y; Tree[y].fa=x; if(!Tree[y].OnPath){ Tree[y].OnPath=1; Tree[x].OnPath=0; } } else{ Tree[y].r=Tree[x].l; if(Tree[x].l)Tree[Tree[x].l].fa=y; if(Tree[y].OnPath){ if(Tree[z].l==y)Tree[z].l=x; else Tree[z].r=x; } Tree[x].fa=z; Tree[x].l=y; Tree[y].fa=x; if(!Tree[y].OnPath){ Tree[y].OnPath=1; Tree[x].OnPath=0; } } updata(y); } void Splay(int x){ pushdown(x); while(Tree[x].OnPath){ int y=Tree[x].fa; int z=Tree[y].fa; if(Tree[y].OnPath)pushdown(z); pushdown(y); pushdown(x); if(!Tree[y].OnPath){ Rotate(x); } else if((Tree[z].l==y)==(Tree[y].l==x)){ Rotate(y); Rotate(x); } else {Rotate(x);Rotate(x);} } updata(x); } void ACCESS(int u){ int v=0; while(u){ Splay(u); Tree[Tree[u].r].OnPath=0; Tree[u].r=v; Tree[v].OnPath=1; // updata(u); v=u; u=Tree[u].fa; } } void Make_Root(int x){ ACCESS(x); Splay(x); Tree[x].rev^=1; } void link(int x,int y){ Make_Root(x); Tree[x].fa=y; } void make(int x){ Make_Root(n+1); ACCESS(x); Splay(x); } void Cut(int x,int y){ Make_Root(x); ACCESS(y); Splay(y); Tree[Tree[y].l].OnPath=Tree[y].l=Tree[x].fa=0; } int Getint(){ char ch=getchar(); while(ch<'0'||ch>'9')ch=getchar(); int ret=0; while(ch<='9'&&ch>='0')ret=ret*10+ch-'0',ch=getchar(); return ret; } char bur[10]; void putint(int i){ int p=0; if(i==0)p++; while(i){ bur[p++]=i%10; i/=10; } for(int j=p-1;j>=0;j--)putchar('0'+bur[j]); } int main(){ // freopen("a.in","r",stdin); // freopen("a.out","w",stdout); n=Getint(); int a,b; for(int i=1;i<=n;i++){ a=Getint(); next[i]=min(i+a,n+1); link(i,next[i]); } int m; scanf("%d",&m); int t; for(int i=1;i<=m;i++){ t=Getint(); if(t==1){ a=Getint(); a++; make(a); putint(Tree[a].size-1); putchar('\n'); } if(t==2){ a=Getint(); b=Getint(); a++; int temp=min(n+1,a+b); if(next[a]!=temp){ Cut(a,next[a]); next[a]=temp; link(a,next[a]); } } } return 0; } /* 4 1 2 1 1 3 1 1 2 1 1 1 1 2 3 */
附一份AC代码: http://blog.csdn.net/qq_30303087/article/details/50670728
相关文章推荐
- perl 数组跟哈希
- perl 登录人人,并发送帖子
- MFC消息机制---消息映射
- 驾照考试:理论考试注意事项
- 光谱学
- perl 文件句柄
- mysql参数设置与查看
- 一个下音乐的方法
- 模拟计算器进行四则运算(同等优先级)(内测第2届第3题)
- 微信现在越来越难开了,有什么办法可以快速开很多微信号呢
- 驾照考试:科目二考试注意事项
- 第一篇博文
- 用V4包中的DrawerLayout实现下拉刷…
- 模仿微信6.0的界面效果
- 自定义的上下拉刷新和SwipeListVie…
- Android获取屏幕宽度与长度的三个…
- 解决ListView在ScrollView中无法展…
- 如何用android&nbsp;sharedprefere…
- Android应用程序中,activity的管…
- perl print 与 加减乘除