[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;
}
}
}