LOJ #6277. 數列分塊入門 1

題目鏈接

思路&&代碼

區間修改+單點查值

先分塊,把這nn個數分成n\sqrt{n}個塊,用add[i]add[i]表示這個塊修改值的和(增量標記)

區間修改:如果是修改整個塊,則直接修改這個塊的增量標記,如果不是一整個塊,就暴力修改值,如果是多個塊,是整塊的修改增量標記,不是整塊的暴力修改

單點查值:單點查值的結果就是這個位置的值加上這個位置所在塊的增量標記的值

時間複雜度O(nn)O(n\sqrt{n})

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#define int long long
using namespace std;

const int A = 1e5 + 11;

inline int read() {
	char c = getchar(); int x = 0, f = 1;
	for ( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
	for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
	return x * f;
}

int n, m, t;
int a[A], add[A], L[A], R[A], pos[A];

void change(int l, int r, int c) {
	int p = pos[l], q = pos[r];
	if(p == q) {
		for(int i = l; i <= r; i++) a[i] += c;
		return;
	}
	for(int i = p + 1; i < q; i++) add[i] += c;
	for(int i = l; i <= R[p]; i++) a[i] += c;
	for(int i = L[q]; i <= r; i++) a[i] += c;
}

int ask(int now) {
	int p = pos[now];
	return a[now] + add[p];
}

signed main() {
	n = read();
	for(int i = 1; i <= n; i++) a[i] = read();
	t = sqrt(n);
	for(int i = 1; i <= t; i++) {
		L[i] = (i - 1) * sqrt(n) + 1;
		R[i] = i * sqrt(n);
	}
	if(R[t] < n) t++, L[t] = R[t - 1] + 1, R[t] = n;
	for(int i = 1; i <= t; i++) {
		for(int j = L[i]; j <= R[i]; j++) {
			pos[j] = i;
		}
	}
	m = n;
	while(m--) {
		int opt, l, r, c;
		opt = read(), l = read(), r = read(), c = read();
		if(opt == 0) change(l, r, c);
		else cout << ask(r) << "\n";
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章