分块做法玄学块长求助
查看原帖
分块做法玄学块长求助
750618
elsc楼主2024/4/3 21:08

(我没看题解,写法可能有一点不同,但思路是一样的) 我用静态区间块长,像这样:

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

constexpr int len = 128;
constexpr int maxn = 2e5 + 5;
constexpr int maxb = maxn / len + 1;
int n, q;
#define from(i) ((i)/len)
#define leftp(i) ((i)*len)
#define rightp(i) (leftp((i)+1)-1)

int step[maxn];
int a[maxn];
int pos[maxn];

void upd(int i, int x) {
	int s = from(i), t = i + x;
	step[i] = x;
	
	if (t <= rightp(s)) a[i] = a[t] + 1, pos[i] = pos[t];
	else a[i] = 1, pos[i] = t;
	
	for (int k = i - 1, l = leftp(s), r = rightp(s); k >= l; --k) {
		int t = k + step[k];
		if (t <= r) {
			a[k] = a[t] + 1, pos[k] = pos[t];
		}
	}
}

int query(int i) {
	int cnt = 0;
	while (i < n) {
		cnt += a[i];
		i = pos[i];
	}
	return cnt;
}

int main() {
	ios::sync_with_stdio(false); cin.tie(0);
	cin >> n;
	for (int i = 0; i < n; ++i) {
		cin >> step[i];
	}
	for (int i = 0; i < n; ++i) {
		int r = min(rightp(from(i)), n - 1);
		int cnt = 0, k = i;
		do ++cnt, k += step[k];
		while (k <= r);
		a[i] = cnt, pos[i] = k;
	}
	
	cin >> q;
	for (int t = 0; t < q; ++t) {
		int op; cin >> op;
		if (op == 1) {
			int j; cin >> j;
			cout << query(j) << '\n';
		} else {
			int j, k; cin >> j >> k;
			upd(j, k);
		}
	}
	return 0;
}

块长取255: 块长取107: ??? 动态区间块长:

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

int len;
constexpr int maxn = 2e5 + 5;
int n, q;
#define from(i) ((i)/len)
#define leftp(i) ((i)*len)
#define rightp(i) (leftp((i)+1)-1)

int step[maxn];
int a[maxn];
int pos[maxn];

void upd(int i, int x) {
	int s = from(i), t = i + x;
	step[i] = x;
	
	if (t <= rightp(s)) a[i] = a[t] + 1, pos[i] = pos[t];
	else a[i] = 1, pos[i] = t;
	
	for (int l = leftp(s), r = rightp(s), k = r; k >= l; --k) {
		int t = k + step[k];
		if (t <= r) {
			a[k] = a[t] + 1, pos[k] = pos[t];
		} else {
		    a[k] = 1, pos[k] = t;
		}
	}
}

int query(int i) {
	int cnt = 0;
	while (i < n) {
		cnt += a[i];
		i = pos[i];
	}
	return cnt;
}

int main() {
	ios::sync_with_stdio(false); cin.tie(0);
	cin >> n; len = sqrt(n);
	for (int i = 0; i < n; ++i) {
		cin >> step[i];
	}
	for (int i = 0; i < n; ++i) {
		int r = min(rightp(from(i)), n - 1);
		int cnt = 0, k = i;
		do ++cnt, k += step[k];
		while (k <= r);
		a[i] = cnt, pos[i] = k;
	}
	
	cin >> q;
	for (int t = 0; t < q; ++t) {
		int op; cin >> op;
		if (op == 1) {
			int j; cin >> j;
			cout << query(j) << '\n';
		} else {
			int j, k; cin >> j >> k;
			upd(j, k);
		}
	}
	return 0;
}

所以???(大雾

2024/4/3 21:08
加载中...