bzoj2002Bounce 弹飞绵羊 动态树(Link-Cut-Tree)
2017-09-14 20:23
246 查看
2002: [Hnoi2010]Bounce 弹飞绵羊
Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 11830 Solved: 5986
[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<=100000Output
对于每个i=1的情况,你都要输出一个需要的步数,占一行。Sample Input
41 2 1 1
3
1 1
2 1 1
1 1
Sample Output
23
HINT
Source
题目大意:动态修改询问一个点到链尾的距离。裸的动态树。
其实可以不裸。
考虑修改,Link的时候,我们考虑把点怼到辅助树的根的时候,左边是他的爸爸们,也就是从这个点到链尾的所与节点。这个时候,需要把它和后面的链点断开,所以直接在辅助树上把它和它的左子树断开(记得儿子父亲都要断)。然后重新连链就可以了。酱紫的话,连rev,makeroot,cut,pushdown什么的都不用啦,效率还可以。
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<cmath>
#define maxn 220000
#define ls t[p].ch[0]
#define rs t[p].ch[1]
#define pa t[p].f
using namespace std;
int read() {
char ch = getchar(); int x = 0, f = 1;
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = x * 10 - '0' + ch; ch = getchar();}
return x * f;
}
struct node {
int f, ch[2];
int s;
}t[maxn]; int n, m;
bool wh(int p) {return t[pa].ch[1] == p;}
bool Isroot(int p) {return t[pa].ch[0] != p && t[pa].ch[1] != p;}
void update(int p) {t[p].s = t[ls].s + t[rs].s + 1;}
void Rotate(int p) {
int f = pa, g = t[f].f, c = wh(p);
if(!Isroot(f)) t[g].ch[wh(f)] = p; t[p].f = g;
t[f].ch[c] = t[p].ch[c ^ 1]; if(t[f].ch[c]) t[t[f].ch[c]].f = f;
t[p].ch[c ^ 1] = f; t[f].f = p;
update(f);
}
void Splay(int p) {
for(; !Isroot(p); Rotate(p))
if(!Isroot(pa)) Rotate(wh(p) == wh(pa) ? pa : p);
update(p);
}
void Access(int p) {
for(int pre = 0; p; pre = p, p = pa) {
Splay(p);
t[p].ch[1] = pre;
update(p);
}
}
void Link(int p, int g) {
Access(p); Splay(p);
t[ls].f = 0; ls = 0;
pa = g; update(p);
}
void Query(int p) {Access(p); Splay(p); printf("%d\n", t[ls].s + 1);}
int main()
{
n = read();
for(int i = 1;i <= n; ++i) {
int k = read(); t[i].s = 1;
if(i + k <= n) Link(i, i + k);
}
m = read();
for(int i = 1;i <= m; ++i) {
int opt = read();
if(opt == 1) Query(read() + 1);
else {
int x = read() + 1, y = read();
if(x + y > n) Link(x, 0);
else Link(x, x + y);
}
}
return 0;
}
相关文章推荐
- [bzoj2002][Hnoi2010]Bounce 弹飞绵羊 分块 Link-Cut-Tree
- 【bzoj2002】[Hnoi2010]Bounce 弹飞绵羊 link-cut-tree
- Link-Cut-Tree:【BZOJ2002】弹飞绵羊
- BZOJ 2002 弹飞绵羊 Link-Cut-Tree(LCT)
- 2002: [Hnoi2010]Bounce 弹飞绵羊(link-cut-tree)
- bzoj 2002: 弹飞绵羊 Link-Cut-Tree
- BZOJ 2002 弹飞绵羊 Link-Cut-Tree(LCT)
- [BZOJ2002] [HNOI2010] 弹飞绵羊 - Link-Cut-Tree (LCT)
- bzoj 2002 LinkCutTree
- BZOJ 2631 tree 动态树(Link-Cut-Tree)
- bzoj2002 [Hnoi2010]Bounce 弹飞绵羊 (Link Cut Tree)
- bzoj 2002 HNOI 2010 弹飞绵羊 bounce [Link-Cut Tree]
- BZOJ 2002 [Hnoi2010]Bounce 弹飞绵羊 ——Link-Cut Tree
- 【bzoj2002】[Hnoi2010]Bounce 弹飞绵羊 动态树
- bzoj 2002 link cut tree(LCT)
- BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊 动态树
- BZOJ 题目2002: [Hnoi2010]Bounce 弹飞绵羊(link cut tree)
- bzoj 2002: [Hnoi2010]Bounce 弹飞绵羊
- BZOJ 2908 又是nand Link-Cut-Tree
- BZOJ.2002.Bounce 弹飞绵羊(LCT)