- 序列上的带修跳跃(弹飞绵羊)
1
- @ 2026-8-2 11:05:33
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int, int>
void solve() {
int n;
cin >> n;
vector<int> a(n + 1);
for (int i = 1; i <= n; i++) cin >> a[i], a[i] += i;
vector<int> f(n + 1), g(n + 1);
int B = sqrt(n);
int C = (n + B - 1) / B;
vector<int> bel(n + 1), st(C + 1), ed(C + 1);
for (int i = 1; i <= C; i++) {
st[i] = (i - 1) * B + 1, ed[i] = min(n, i * B);
for (int j = st[i]; j <= ed[i]; j++) {
bel[j] = i;
}
}
auto work = [&] (int j) {
for (int i = ed[j]; i >= st[j]; i--) {
if (a[i] > ed[j]) {
f[i] = a[i], g[i] = 1;
} else {
f[i] = f[a[i]], g[i] = 1 + g[a[i]];
}
}
};
for (int i = 1; i <= C; i++) work(i);
auto query = [&] (int x) {
int res = 0;
int c = 0;
while (x <= n) {
res += g[x];
x = f[x];
c++;
}
assert(c <= n / B + 10);
return res;
};
auto change = [&] (int x, int y) {
a[x] = y + x;
work(bel[x]);
};
int m;
cin >> m;
while (m--) {
int o, x, y;
cin >> o >> x; x++;
if (o == 1) {
cout << query(x) << '\n';
} else {
cin >> y;
change(x, y);
// for (int i = 1; i <= n; i++) cout << f[i] << " \n" [i == n];
// for (int i = 1; i <= n; i++) cout << g[i] << " \n" [i == n];
}
}
}
signed main() {
ios::sync_with_stdio(0); cin.tie(0);
int t = 1;
// cin >> t;
while (t--) solve();
return 0;
}
g++ -std=c++17 1.cpp -o 1 && 1 < in.txt > out.txt
g++ -std=c++17 1.cpp -o 1 && ./1 < in.txt > out.txt
***/
0 条评论
目前还没有评论...
信息
- ID
- 540
- 时间
- ms
- 内存
- MiB
- 难度
- 6
- 标签
- 递交数
- 31
- 已通过
- 11
- 上传者