[CF13E] Holes

[CF13E] Holes - 分块

Description

(N) 个洞,每个洞有相应的弹力,能把这个球弹到 (i+power[i]) 位置。共有两种操作:把 (a) 位置的弹力改成 (b);在 (a) 处放一个球,输出最后一次落在哪个洞,球被弹出前共被弹了多少次。

Solution

分块,记录每个块内每个位置弹出该块的时间 tim[i] 和弹出到的位置 pos[i]

#include <bits/stdc++.h>
using namespace std;

const int N = 100005;
const int B = 450;

int bel[N], tim[N], pos[N], lpos[N], power[N], n, m;

int block_min(int i)
{
    return i * B - B + 1;
}

int block_max(int i)
{
    return i * B;
}

void presolve(int l, int r)
{
    r = min(r, n);
    for (int i = r; i >= l; i--)
    {
        int p = i + power[i];
        if (p > block_max(bel[i]) || p > n)
        {
            tim[i] = 1;
            pos[i] = p;
            lpos[i] = i;
        }
        else
        {
            tim[i] = tim[p] + 1;
            pos[i] = pos[p];
            lpos[i] = lpos[p];
        }
    }
}

signed main()
{
    ios::sync_with_stdio(false);

    cin >> n >> m;

    for (int i = 1; i <= n; i++)
        cin >> power[i];

    for (int i = 1; i <= n; i++)
        bel[i] = (i - 1) / B + 1;

    presolve(1, n);

    for (int i = 1; i <= m; i++)
    {
        int t, a, b;
        cin >> t;
        if (t == 0)
        {
            cin >> a >> b;
            power[a] = b;
            presolve(block_min(bel[a]), block_max(bel[a]));
        }
        else
        {
            cin >> a;
            int _tim = 0, _pos = a, _lpos = a;
            while (_pos <= n)
            {
                _tim += tim[_pos];
                _lpos = lpos[_pos];
                _pos = pos[_pos];
            }
            cout << _lpos << " " << _tim << endl;
        }
    }
}
原文地址:https://www.cnblogs.com/mollnn/p/14357331.html