[BZOJ 2002] 弹飞绵羊 LCT

题意

  给定 n 个装置, 每个装置有系数 K[i] .

  在点 i 的绵羊会被弹到 i + K[i] , 如果 i + K[i] > n , 则定义为被弹飞.

  m 次操作, 每次操作是下面的某种:

    ① 更改某个装置的系数 K[x] = y .

    ② 问一只从装置 x 出发的绵羊几次被弹飞.

  n <= 200000 .

实现

  1. 不需要换根.

  2.  par[x] 指当前子树中深度最小的点的父亲.

    c[x][0] 的子树指深度比当前点小的一些祖先.

    c[x][1] 的子树指深度比当前点大的一条后继.

    这样理解会比 [ 肤浅地认为是 Splay 的相关信息 ] 要好.

  3. Expose(x)

    Splay(x) , c[x][1] = t, Up(x), t = x, x = par[x] .

        用 2. 解释 c[x][1] = t .

  4. Link(x, y)

    Splay(x), par[x] = y .

  5. Cut(x, y)

    Expose(x), Splay(x), par[c[x][0]] = 0, c[x][0] = 0, Up(x) .

              用 2. 解释后面三个操作.

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cctype>
 5 #define F(i, a, b) for (register int i = (a); i <= (b); i++)
 6 inline int rd(void) {
 7     int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == ‘-‘) f = -1;
 8     int x = 0; for (; isdigit(c); c = getchar()) x = x*10+c-‘0‘; return x*f;
 9 }
10
11 const int N = 200005;
12
13 int n, K[N];
14 int par[N], c[N][2], siz[N];
15
16 inline void Up(int x) { siz[x] = siz[c[x][0]] + siz[c[x][1]] + 1; }
17
18 inline bool Root(int x) { return c[par[x]][0] != x && c[par[x]][1] != x; }
19 inline void Rot(int x) {
20     int t = par[x], z = par[t];
21     int L = (c[t][1] == x), R = L^1;
22
23     if (!Root(t))
24         c[z][c[z][1] == t] = x;
25     par[x] = z;
26
27     if (c[x][R] > 0)
28         par[c[x][R]] = t;
29     c[t][L] = c[x][R];
30
31     c[x][R] = t, par[t] = x;
32     Up(t), Up(x);
33 }
34 inline void Splay(int x) {
35     for (; !Root(x); Rot(x)) {
36         int y = par[x], z = par[y];
37         if (!Root(y))
38             (c[y][0] == x) ^ (c[z][0] == y) ? Rot(x) : Rot(y);
39     }
40 }
41
42 inline void Expose(int x) {
43     for (int t = 0; x > 0; t = x, x = par[x]) {
44         Splay(x);
45         c[x][1] = t, Up(x);
46     }
47 }
48 inline void Link(int x, int y) { Splay(x), par[x] = y; }
49 inline void Cut(int x) {
50     Expose(x);
51     Splay(x);
52     par[c[x][0]] = 0, c[x][0] = 0, Up(x);
53 }
54 inline int Query(int x) {
55     Expose(x);
56     Splay(x);
57     return siz[x];
58 }
59
60 int main(void) {
61     #ifndef ONLINE_JUDGE
62         freopen("xsy2531.in", "r", stdin);
63     #endif
64
65     n = rd();
66     F(i, 1, n) siz[i] = 1;
67
68     F(i, 1, n) K[i] = rd();
69     F(i, 1, n) if (i + K[i] <= n)
70         Link(i, i + K[i]);
71
72     int m = rd();
73     F(i, 1, m) {
74         int k = rd();
75         if (k == 1) {
76             int x = rd() + 1;
77             printf("%d\n", Query(x));
78         }
79         else {
80             int x = rd() + 1, y = rd();
81             if (x + K[x] <= n) Cut(x);
82             K[x] = y;
83             if (x + K[x] <= n) Link(x, x + K[x]);
84         }
85     }
86
87     return 0;
88 }
时间: 2025-01-13 19:43:06

[BZOJ 2002] 弹飞绵羊 LCT的相关文章

BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊( LCT )

LCT... ---------------------------------------------------------------- #include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #define rep( i , n ) for( int i = 0 ; i < n ; ++i ) #define clr( x , c ) memset( x

bzoj2002 弹飞绵羊 LCT

2002: [Hnoi2010]Bounce 弹飞绵羊 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 6706  Solved: 3522[Submit][Status][Discuss] Description 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹ki

[HNOI2010][BZOJ2002] 弹飞绵羊 - LCT

Description 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹ki步,达到第i+ki个装置,若不存在第i+ki个装置,则绵羊被弹飞.绵羊想知道当它从第i个装置起步时,被弹几次后会被弹飞.为了使得游戏更有趣,Lostmonkey可以修改某个弹力装置的弹力系数,任何时候弹力系数均为正整数. Input & O

[BZOJ2002][Hnoi2010]Bounce弹飞绵羊 LCT

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2002 建图,每次往后面跳就往目标位置连边,将跳出界的点设为同一个点.对于修改操作发现可以用LCT维护图的连通性,然后用size域维护跳的点的次数就行了. 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 int inline readint(

BZOJ2002: [Hnoi2010]Bounce 弹飞绵羊 LCT

这道题的lct不想说什么...... 这道题是lct的假板子题你需要精简并适当改进LCT给他加上不清真的属性...... #include<cstdio> #include<cstring> #define MAXN 200010 using namespace std; struct spaly { spaly *ch[2],*f; int size; void pushup() { size=ch[1]->size+ch[0]->size+1; } }null[MA

BZOJ2002 HNOI2010 弹飞绵羊 LCT

LCT=树链剖分+平衡树(多用Splay),AC之后才对这个等式深有感触-- 我们定义一个操作Access(x),这个操作可以将从x到根节点路径上的所有节点放到一颗Splay里,一切操作都在这棵Splay里做.你说要维护任意两个点的路径?反正是无向树换一下根不就好了-- 我们以执行Access的顺序为权值来进行树链剖分,每一条链用一颗Splay按照深度来维护,每一颗Splay与他的父亲(由于一条链一定是在一个点u的子树上,所以我们只需要让这颗Splay的根与u相连就好,无所谓根和u在原树中是否相

【BZOJ】2002: [Hnoi2010]Bounce 弹飞绵羊(lct)

(BZOJ挂了,还没在BZOJ测,先是在wikioi测过了,,) 囧.在军训时立志要学lct!!!这是一道lct的裸题,只有access操作(10行都没有啊亲...缩行大法的话,我就不说了..)(link操作相当于水过),其实lct很简单..想想都有点小激动...... lct用splay维护的话,一下就写好了..但是我在写lct的时候,发现了一些我原来splay的老问题,我原来也知道了的,就是将null的ch给赋值了,因为在rot操作里没有特判,所以导致了null的孩子被赋值了,导致我的lct

bzoj 2002 : [Hnoi2010]Bounce 弹飞绵羊 (LCT)

链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2002 题面: 2002: [Hnoi2010]Bounce 弹飞绵羊 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 15763  Solved: 8080[Submit][Status][Discuss] Description 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开

BZOJ 题目2002: [Hnoi2010]Bounce 弹飞绵羊(link cut tree)

2002: [Hnoi2010]Bounce 弹飞绵羊 Time Limit: 10 Sec  Memory Limit: 259 MB Submit: 5421  Solved: 2863 [Submit][Status][Discuss] Description 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹