前言:
先说句闲话,分块这个东西其实在第二次集训刚刚开始的时候就拉着lc学过一阵,原因是在luogu上见到了某著名毒瘤出的末日时系列的一套题目,貌似大部分都是分块,于是我想尝试着去做几道(毕竟是个珂学家),但是看完题目就自闭了(noip毒瘤果不虚传),这两天学长又给我们讲了一些分块的知识,就把loj上的几道入门题再捡起来说一下吧。
入门基础知识就不说什么了,学长讲过了,蓝皮书上面也有。
这里前面和后面的代码风格可能不太一样,8之前的都是在学长讲课之前写的,9照学长代码修改了一些地方。
数列分块入门 1
基础的操作,之前学过的线段树树状数组也都可以很好的解决,如果不是为了刻意练习分块的话以后见到建议树状数组(逃)
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 }