题目链接:#6277. 数列分块入门 1
题目大意
给出一个长为 (n) 的数列,以及 (n) 个操作,操作涉及区间加法,单点查值。
solution
我们可以用树状数组和线段树来过掉他, 但是这是一道分块的题,那我们就要用分块来 (A) 掉它
查询操作: 我们可以直接记录一下块的操作,然后查询的时候将原来的元素加上记录的即可
修改操作: 我们可以让不足块大小的单独处理, 然后每个块一起处理
Code:
/**
* Author: Alieme
* Data: 2020.9.8
* Problem: LibreOJ #6277
* Time: O()
*/
#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
#include <cmath>
#include <algorithm>
#define int long long
#define rr register
#define inf 1e9
#define MAXN 100010
using namespace std;
inline int read() {
int s = 0, f = 0;
char ch = getchar();
while (!isdigit(ch)) f |= ch == '-', ch = getchar();
while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar();
return f ? -s : s;
}
void print(int x) {
if (x < 0) putchar('-'), x = -x;
if (x > 9) print(x / 10);
putchar(x % 10 + 48);
}
int n, len;
int a[MAXN], s[MAXN], id[MAXN], b[MAXN];
inline void add(int l, int r, int x) {
int start = id[l], end = id[r];
if (start == end) {
for (rr int i = l; i <= r; i++) a[i] += x, s[start] += x;
return ;
}
for (rr int i = l; id[i] == start; i++) a[i] += x, s[start] += x;
for (rr int i = start + 1; i < end; i++) b[i] += x, s[i] += len * x;
for (rr int i = r; id[i] == end; i--) a[i] += x, s[end] += x;
}
inline int query(int r) {
return a[r] + b[id[r]];
// int start = id[l], end = id[r], ans = 0;
// if (start == end) {
// for (rr int i = l; i <= r; i++) ans += a[i] + b[start];
// return ans;
// }
// for (rr int i = l; id[i] == start; i++) ans += a[i] + b[start];
// for (rr int i = start + 1; i < end; i++) ans += s[i];
// for (rr int i = r; id[i] == end; i--) ans += a[i] + b[end];
// return ans;
}
signed main() {
n = read();
len = sqrt(n);
for (rr int i = 1; i <= n; i++) {
a[i] = read();
id[i] = (i - 1) / len + 1;
s[id[i]] += a[i];
}
while (n--) {
int opt = read(), l = read(), r = read(), c = read();
if (opt == 0) add(l, r, c);
if (opt == 1) cout << query(r) << "
";
}
}