前言:

先说句闲话,分块这个东西其实在第二次集训刚刚开始的时候就拉着lc学过一阵,原因是在luogu上见到了某著名毒瘤出的末日时系列的一套题目,貌似大部分都是分块,于是我想尝试着去做几道(毕竟是个珂学家),但是看完题目就自闭了(noip毒瘤果不虚传),这两天学长又给我们讲了一些分块的知识,就把loj上的几道入门题再捡起来说一下吧。

入门基础知识就不说什么了,学长讲过了,蓝皮书上面也有。

这里前面和后面的代码风格可能不太一样,8之前的都是在学长讲课之前写的,9照学长代码修改了一些地方。

数列分块入门 1

loj数列分块入门 1~9

 基础的操作,之前学过的线段树树状数组也都可以很好的解决,如果不是为了刻意练习分块的话以后见到建议树状数组(逃)

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N = 1e6 + 10;
 4 int block, a[N], add[N], belong[N], sum[N], siz[N];
 5 void change(int l, int r, int num) {
 6     for (int i = l; i <= min(r, belong[l] * block); ++i) {
 7         a[i] += num;
 8         sum[belong[i]] += num;
 9     }
10     if (belong[l] == belong[r])
11         return;
12     for (int i = r; i >= (belong[r] - 1) * block + 1; --i) {
13         a[i] += num;
14         sum[belong[i]] += num;
15     }
16     for (int i = belong[l] + 1; i <= belong[r] - 1; ++i) {
17         add[i] += num;
18     }
19 }
20 int main() {
21     int n;
22     scanf("%d", &n);
23     for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
24     block = (int)sqrt(n);
25     for (int i = 1; i <= n; ++i) {
26         belong[i] = (i - 1) / block + 1;
27         siz[belong[i]]++;
28         sum[belong[i]] += a[i];
29     }
30     for (int i = 1; i <= n; ++i) {
31         int t, x, y, z;
32         scanf("%d%d%d%d", &t, &x, &y, &z);
33         if (t == 0) {
34             change(x, y, z);
35         } else {
36             printf("%d\n", a[y] + add[belong[y]]);
37         }
38     }
39     return 0;
40 }
View Code

相关文章: