数列分块入门
分块入门
LibreOJ - 6277
#include <bits/stdc++.h>
using namespace std;
template <typename T> inline void read(T& t)
{
int f = 0, c = getchar();
t = 0;
while (!isdigit(c)) f |= c == '-', c = getchar();
while (isdigit(c)) t = t * 10 + c - 48, c = getchar();
if (f) t = -t;
}
const int N = 5e4 + 100;
int bk, num;
int n, a[N], L[N], R[N], pos[N], lazy[N];
inline void build()
{
bk = sqrt(n);
num = n / bk;
if(n % bk) num++;
for(int i = 1; i <= num; ++i)
{
L[i] = (i - 1) * bk + 1;
R[i] = i * bk;
}
R[num] = n;
for(int i = 1; i <= n; ++i) pos[i] = (i - 1) / bk + 1;
}
inline void change(int l, int r, int k)
{
int idx1 = pos[l];
int idx2 = pos[r];
if(idx1 == idx2)
{
for(int i = l; i <= r; ++i) a[i] += k;
}
else
{
for(int i = l; i <= R[idx1]; ++i) a[i] += k;
for(int i = pos[l] + 1; i <= pos[r] - 1; ++i) lazy[i] += k;
for(int i = L[idx2]; i <= r; ++i) a[i] += k;
}
}
inline int query(int i)
{
int idx = pos[i];
return lazy[idx] ? lazy[idx] + a[i] : a[i];
}
signed main()
{
read(n);
for(int i = 1; i <= n; ++i) read(a[i]);
build();
int op, l, r, c;
for(int i = 1; i <= n; ++i)
{
read(op), read(l), read(r), read(c);
if(op == 0)
{
change(l, r, c);
}
else printf("%d\n", query(r));
}
return 0;
}
LibreOJ - 6278
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5 + 10;
//bk:块大小 num:块数量
int bk, num;
//每个块的左端点L 右端点R 位于哪个块pos 每个块的lazy标记
int n, a[N], L[N], R[N], pos[N], lazy[N];
vector<int> g[N];//排序桶块 将每一块的元素扔进一个桶 然后排序
inline void build()
{
bk = sqrt(n);
num = n / bk;// n / 块大小 = 块数
if(n % bk) num++; // 如果不能整除 代表多了一个块
for(int i = 1; i <= num; ++i)
{
L[i] = (i - 1) * bk + 1;
R[i] = i * bk;
}
R[num] = n;
for(int i = 1; i <= n; ++i) pos[i] = (i - 1) / bk + 1;//处理位置
for(int i = 1; i <= num; ++i)
{
for(int j = L[i]; j <= R[i]; ++j) g[i].push_back(a[j]);
sort(g[i].begin(), g[i].end());
}
}
//暴力再更新这个块内的排序
inline void resort(int i)
{
g[i].clear();
for(int j = L[i]; j <= R[i]; ++j) g[i].push_back(a[j]);
sort(g[i].begin(), g[i].end());
}
inline void change(int x, int y, int c)
{
//如果在同一个块内 暴力更新
if(pos[x] == pos[y])
{
for(int i = x; i <= y; ++i) a[i] += c;
resort(pos[x]);
return;
}
//暴力更新左边
for(int i = x; i <= R[pos[x]]; ++i) a[i] += c;
resort(pos[x]);
//对于中间完整的块打上lazy tag
for(int i = pos[x] + 1; i < pos[y]; ++i) lazy[i] += c;
//暴力更新右边
for(int i = L[pos[y]]; i <= y; ++i) a[i] += c;
resort(pos[y]);
}
inline int query(int x, int y, int c)
{
int res = 0;
//如果在同一块内
if(pos[x] == pos[y])
{
for(int i = x; i <= y; ++i) res += (a[i] + lazy[pos[x]] < c);
return res;
}
//左边
for(int i = x; i <= R[pos[x]]; ++i) res += (a[i] + lazy[pos[x]] < c);
//中间
for(int i = pos[x] + 1; i < pos[y]; ++i)
{
int k = lower_bound(g[i].begin(), g[i].end(), c - lazy[i]) - g[i].begin();
res += k;
}
//右边
for(int i = L[pos[y]]; i <= y; ++i) res += (a[i] + lazy[pos[y]] < c);
return res;
}
signed main()
{
cin >> n;
for(int i = 1; i <= n; ++i) cin >> a[i];
build();
int op, l, r, c;
for(int i = 1; i <= n; ++i)
{
cin >> op >> l >> r >> c;
if(op == 0) change(l, r, c);
else cout << query(l, r, c * c) << "\n";
}
return 0;
}

浙公网安备 33010602011771号