分块可以干什么???
区间修改,区间求值,还可以求一些线段树不容易达成的目标,比方说是区间大于K的数有多少个。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 10;
int n, m, block, belong[maxn], _left[maxn], _right[maxn], num, a[maxn], inc[maxn] = {0};
ll sum[maxn];
void build()
{
block = sqrt(n);
num = n / block;
if(n % block) num++;
for(int i = 1; i <= num; i++) {
_left[i] = (i - 1) * block + 1;
_right[i] = i * block;
}
_right[num] = n;
for(int i = 1; i <= num; i++) {
for(int j = _left[i]; j <= _right[i]; j++) {
belong[j] = i;
sum[i] += a[j];
}
}
}
ll ask(int l, int r) {
ll ret = 0;
if(belong[l] == belong[r]) {
for(int i = l; i <= r; i++) {
ret += a[i];
}
}
else {
for(int i = l; i <= _right[belong[l]]; i++) {
ret += a[i] + inc[belong[i]];
}
for(int i = belong[l] + 1; i < belong[r]; i++) {
ret += sum[i] + inc[i] * block;
}
for(int i = _left[belong[r]]; i <= r; i++) {
ret += a[i] + inc[belong[i]];
}
}
return ret;
}
void update(int l, int r, int d) {
if(belong[l] == belong[r]) {
for(int i = l; i <= r; i++) {
a[i]+=d;
sum[belong[l]] += d;
}
}
else {
for(int i = l; i <= _right[belong[l]]; i++) {
a[i] += d;
sum[belong[l]]+=d;
}
for(int i = belong[l] + 1; i < belong[r]; i++) {
inc[i] += d;
}
for(int i = _left[belong[r]]; i <= r; i++) {
a[i] += d;
sum[belong[r]]+=d;
}
}
}
int main()
{
// freopen("i.txt", "r", stdin);
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
build();
while(m--) {
int op;
scanf("%d", &op);
if(op == 2) {
int l, r;
scanf("%d%d", &l, &r);
printf("%lld\n", ask(l,r));
}
else {
int l, r, d;
scanf("%d%d%d", &l, &r, &d);
update(l, r, d);
}
}
return 0;
}
/*
5 5
1 5 4 2 3
2 2 4
1 2 3 2
2 3 4
1 1 5 1
2 1 4
*/