博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ2002: [Hnoi2010]Bounce 弹飞绵羊(LCT)
阅读量:5324 次
发布时间:2019-06-14

本文共 3885 字,大约阅读时间需要 12 分钟。

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,很显然要让 i 与 i 能到的点连边,yy一个不存在的点n+1,让所有点与它连边表示弹飞。

更改时先Cut后Link

最后查询时将n+1与x路径提取,查询重量即可(注意要-1^_^)

代码:

1 #include
2 #include
3 #include
4 #define lll tr[spc].ch[0] 5 #define rrr tr[spc].ch[1] 6 #define ls ch[0] 7 #define rs ch[1] 8 const int N=300000; 9 struct trnt{ 10 int ch[2]; 11 int lzt; 12 int fa; 13 int wgt; 14 bool anc; 15 }tr[N]; 16 int nx[N]; 17 int n,m; 18 bool whc(int spc) 19 { 20 return tr[tr[spc].fa].rs==spc; 21 } 22 void pushup(int spc) 23 { 24 tr[spc].wgt=tr[lll].wgt+tr[rrr].wgt+1; 25 return ; 26 } 27 void trr(int spc) 28 { 29 if(!spc) 30 return ; 31 std::swap(lll,rrr); 32 tr[spc].lzt^=1; 33 return ; 34 } 35 void pushdown(int spc) 36 { 37 if(tr[spc].lzt) 38 { 39 tr[spc].lzt=0; 40 trr(lll); 41 trr(rrr); 42 } 43 return ; 44 } 45 void recal(int spc) 46 { 47 if(!tr[spc].anc) 48 recal(tr[spc].fa); 49 pushdown(spc); 50 return ; 51 } 52 void rotate(int spc) 53 { 54 int f=tr[spc].fa; 55 bool k=whc(spc); 56 tr[f].ch[k]=tr[spc].ch[!k]; 57 tr[spc].ch[!k]=f; 58 if(tr[f].anc) 59 { 60 tr[spc].anc=1; 61 tr[f].anc=0; 62 }else 63 tr[tr[f].fa].ch[whc(f)]=spc; 64 tr[spc].fa=tr[f].fa; 65 tr[f].fa=spc; 66 tr[tr[f].ch[k]].fa=f; 67 pushup(f); 68 pushup(spc); 69 return ; 70 } 71 void splay(int spc) 72 { 73 recal(spc); 74 while(!tr[spc].anc) 75 { 76 int ft=tr[spc].fa; 77 if(tr[ft].anc) 78 { 79 rotate(spc); 80 return ; 81 } 82 if(whc(spc)^whc(ft)) 83 rotate(spc); 84 else 85 rotate(ft); 86 rotate(spc); 87 } 88 return ; 89 } 90 void access(int spc) 91 { 92 int lst=0; 93 while(spc) 94 { 95 splay(spc); 96 tr[rrr].anc=1; 97 tr[lst].anc=0; 98 rrr=lst; 99 pushup(spc);100 lst=spc;101 spc=tr[spc].fa;102 }103 return ;104 }105 void Mtr(int spc)106 {107 access(spc);108 splay(spc);109 trr(spc);110 return ;111 }112 void Link(int spc,int y)113 {114 access(spc);115 splay(spc);116 tr[spc].fa=y;117 return ;118 }119 void Cut(int x,int y)120 {121 Mtr(x);122 access(y);123 splay(x);124 tr[x].rs=0;125 tr[y].anc=1;126 tr[y].fa=0;127 return ;128 }129 void split(int x,int y)130 {131 Mtr(x);132 access(y);133 splay(y);134 }135 int dest(int i)136 {137 return (i+nx[i]>n)?(n+1):(i+nx[i]);138 }139 int main()140 {141 scanf("%d",&n);142 for(int i=1;i<=n+1;i++)143 tr[i].anc=1;144 for(int i=1;i<=n;i++)145 {146 scanf("%d",&nx[i]);147 Link(i,dest(i));148 }149 scanf("%d",&m);150 while(m--)151 {152 int i,j,k;153 scanf("%d",&i);154 if(i==1)155 {156 scanf("%d",&j);157 j++;158 split(j,n+1);159 printf("%d\n",tr[n+1].wgt-1);160 }else{161 scanf("%d%d",&j,&k);162 j++;163 Cut(j,dest(j));164 nx[j]=k;165 Link(j,dest(j));166 }167 }168 return 0;169 }

 

转载于:https://www.cnblogs.com/blog-Dr-J/p/9639010.html

你可能感兴趣的文章
[Kali_BT]通过低版本SerialPort蓝牙渗透功能手机
查看>>
C语言学习总结(三) 复杂类型
查看>>
HNOI2018
查看>>
【理财】关于理财的网站
查看>>
Ubunt中文乱码
查看>>
《当幸福来敲门》读后
查看>>
【转】系统无法进入睡眠模式解决办法
查看>>
省市县,循环组装,整合大数组
查看>>
stm32中字节对齐问题(__align(n),__packed用法)
查看>>
like tp
查看>>
posix多线程有感--线程高级编程(线程属性函数总结)(代码)
查看>>
spring-使用MyEcilpse创建demo
查看>>
DCDC(4.5V to 23V -3.3V)
查看>>
kettle导数到user_用于left join_20160928
查看>>
activity 保存数据
查看>>
typescript深copy和浅copy
查看>>
linux下的静态库与动态库详解
查看>>
hbuilder调底层运用,多张图片上传
查看>>
深入理解基于selenium的二次开发
查看>>
较快的maven的settings.xml文件
查看>>