CF 13E Holes 【块状链表】

题目描述:

一条直线上n个点,每个点有个“弹力”,可以把当前位置x上面的ball弹到x+a[x]上面。

两种操作

0. 修改a处的弹力值,编程b

1. 询问a点的ball经过多少次能跳出n个点外(就是出界了)。。。。求出弹跳的次数和最后落脚的点。



块状链表就是用来暴力模拟的。

用块状链表可以把时间复杂度从O(n)变成O(sqrt(n))。

这道题目的复杂度为O(m*sqrt(n))。

具体实现还是直接看代码容易理解……


 

#include <iostream>

#include <algorithm>

#include <cmath>

#include <cstdio>

using namespace std;

#define N 100100

int block[N], c[N], next[N], a[N], end[N];

int n, m, block_size;



void make(int x) {

    int y = x + a[x];

    if (y <= n && block[x] == block[y]) {

        c[x] = c[y] + 1;

        next[x] = next[y];

        end[x] = end[y];

    } else {

        end[x] = x;

        c[x] = 1;

        next[x] = y;

    }

}

void change(int x, int y) {

    a[x] = y;

    for (y=x; y && block[y]==block[x]; y--) make(y);

}



void ask(int x) {

    int ret = 0, ans;

    for (; x<=n; x=next[x]) {

        ret += c[x];

        ans = end[x];

    }

    cout << ans << " " << ret << endl;

}

int main() {



    cin >> n >> m;

    block_size = sqrt(n);



    for (int i=1; i<=n; i++) {

        cin >> a[i];

        block[i] = i/block_size;

    }

    for (int i=n; i; i--) make(i);



    int op, x, y;

    while (m--) {

        cin >> op;

        if (op == 0) {

            cin >> x >> y;

            change(x, y);

        } else {

            cin >> x;

            ask(x);

        }

    }



    return 0;

}


 

 

你可能感兴趣的:(链表)