# 代码解释

st(x)表示$x$块的开始，$block\times x-block+1$
en(x)表示$x$块的结束，$min(block\times x,n)$，其中$n$为整个数列的长度。

# 数列分块1

## ac代码

#include <bits/stdc++.h>
#define ms(a, b) memset(a, b, sizeof(a))
#define LL long long
using namespace std;
inline int gi() {
int w = 0, x = 0;
char ch = 0;
while (!isdigit(ch)) w |= ch == '-', ch = getchar();
while (isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
return w ? -x : x;
}
#define N 50005
int a[N], add[N], pos[N];
int n, block;
void update(int l, int r, int c) {
int ll = pos[l], rr = pos[r];
if (rr - ll <= 1)
for (int i = l; i <= r; i++) a[i] += c;
else {
for (int i = l; i <= ll * block; i++) a[i] += c;
for (int i = ll + 1; i < rr; i++) add[i] += c;
for (int i = (rr - 1) * block + 1; i <= r; i++) a[i] += c;
}
}
int main() {
ms(add, 0);
n = gi();
for (int i = 1; i <= n; i++) a[i] = gi();
block = (int)(sqrt(n) + 0.5);
for (int i = 1; i <= n; i++) pos[i] = (i - 1) / block + 1;
while (n--) {
int opt = gi(), l = gi(), r = gi(), c = gi();
if (opt == 0)
update(l, r, c);
else
printf("%d\n", add[pos[r]] + a[r]);
}
return 0;
}

# 数列分块2

## ac代码

#include <bits/stdc++.h>
#define ms(a, b) memset(a, b, sizeof(a))
#define pb push_back
#define LL long long
using namespace std;
inline int gi() {
int w = 0, x = 0;
char ch = 0;
while (!isdigit(ch)) w |= ch == '-', ch = getchar();
while (isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
return w ? -x : x;
}
int block, n;
#define N 50005
#define st(x) ((x - 1) * block + 1)
#define en(x) (x * block)
vector<int> v[255];
int add[N], a[N], pos[N];
void reset(int x) {
v[x].clear();
for (int i = st(x); i <= min(en(x), n); i++) v[x].pb(a[i]);
sort(v[x].begin(), v[x].end());
}
void update(int l, int r, int c) {
int bl = pos[l], br = pos[r];
if (br - bl <= 1)
for (int i = l; i <= r; i++) a[i] += c;
else {
for (int i = l; i <= en(bl); i++) a[i] += c;
for (int i = st(br); i <= r; i++) a[i] += c;
for (int i = bl + 1; i <= br - 1; i++) add[i] += c;
}
reset(bl);
reset(br);
}
int query(int l, int r, int c) {
int bl = pos[l], br = pos[r], res = 0;
if (bl == br) {
for (int i = l; i <= r; i++)
if (add[bl] + a[i] < c)
res++;
} else if (bl + 1 == br) {
for (int i = l; i <= en(bl); i++)
if (add[bl] + a[i] < c)
res++;
for (int i = st(br); i <= r; i++)
if (add[br] + a[i] < c)
res++;
} else {
for (int i = l; i <= en(bl); i++)
if (add[bl] + a[i] < c)
res++;
for (int i = st(br); i <= r; i++)
if (add[br] + a[i] < c)
res++;
for (int i = bl + 1; i <= br - 1; i++)
res += lower_bound(v[i].begin(), v[i].end(), c - add[i]) - v[i].begin();
}
return res;
}
int main() {
n = gi();
block = (int)(sqrt(n) + 0.5);
for (int i = 1; i <= n; i++) a[i] = gi();
for (int i = 1; i <= n; i++) pos[i] = (i - 1) / block + 1, v[pos[i]].pb(a[i]);
for (int i = 1; i <= pos[n]; i++) sort(v[i].begin(), v[i].end());
for (int i = 1; i <= n; i++) {
int opt = gi(), l = gi(), r = gi(), c = gi();
if (opt == 0)
update(l, r, c);
else
printf("%d\n", query(l, r, c * c));
}
return 0;
}

# 数列分块3

## ac代码

#include <bits/stdc++.h>
#define ms(a, b) memset(a, b, sizeof(a))
#define LL long long
using namespace std;
inline int gi() {
int w = 0, x = 0;
char ch = 0;
while (!isdigit(ch)) w |= ch == '-', ch = getchar();
while (isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
return w ? -x : x;
}
int block, n;
#define N 100005
#define st(x) (block * x - block + 1)
#define en(x) (block * x)
int add[N], a[N], pos[N];
set<int> sett[N];
void reset(int id, int x) {
sett[pos[id]].erase(a[id]);
a[id] += x;
sett[pos[id]].insert(a[id]);
}
void update(int l, int r, int v) {
int bl = pos[l], br = pos[r];
if (br == bl)
for (int i = l; i <= r; i++) reset(i, v);
else {
for (int i = l; i <= en(bl); i++) reset(i, v);
for (int i = st(br); i <= r; i++) reset(i, v);
if (br - bl > 1)
for (int i = bl + 1; i <= br - 1; i++) add[i] += v;
}
}
int query(int l, int r, int c) {
int bl = pos[l], br = pos[r], res = -1;
if (bl == br)
for (int i = l; i <= r; i++) {
if (add[bl] + a[i] < c)
res = max(res, add[bl] + a[i]);
}
else {
for (int i = l; i <= en(bl); i++)
if (add[bl] + a[i] < c)
res = max(res, add[bl] + a[i]);
for (int i = st(br); i <= r; i++)
if (add[br] + a[i] < c)
res = max(res, add[br] + a[i]);
if (br - bl > 1) {
for (int i = bl + 1; i <= br - 1; i++) {
set<int>::iterator it = sett[i].lower_bound(c - add[i]);
if (it == sett[i].begin())
continue;
--it;
res = max(res, *it + add[i]);
}
}
}
return res;
}
int main() {
n = gi();
block = (int)(sqrt(n) + 0.5);
for (int i = 1; i <= n; i++) a[i] = gi();
for (int i = 1; i <= n; i++) pos[i] = (i - 1) / block + 1, sett[pos[i]].insert(a[i]);
for (int cas = 1; cas <= n; cas++) {
int opt = gi(), l = gi(), r = gi(), c = gi();
if (opt == 0)
update(l, r, c);
else
printf("%d\n", query(l, r, c));
}
return 0;
}

# 数列分块4

## 分析

$1$一样，是一道入门的题，区间加法我们已经了解了流程，那么参照区间修改的流程。

## ac代码

#include <bits/stdc++.h>
#define ms(a, b) memset(a, b, sizeof(a))
#define LL long long
using namespace std;
inline int gi() {
int w = 0, x = 0;
char ch = 0;
while (!isdigit(ch)) w |= ch == '-', ch = getchar();
while (isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
return w ? -x : x;
}
inline LL gll() {
LL w = 0, x = 0;
char ch = 0;
while (!isdigit(ch)) w |= ch == '-', ch = getchar();
while (isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
return w ? -x : x;
}
int block, n;
#define st(x) (block * x - block + 1)
#define en(x) (block * x)
#define N 50005
LL sum[N], a[N], add[N];
int pos[N];
void update(int l, int r, LL c) {
int bl = pos[l], br = pos[r];
if (bl == br) {
for (int i = l; i <= r; i++) a[i] += c, sum[bl] += c;
} else {
for (int i = l; i <= en(bl); i++) a[i] += c, sum[bl] += c;
for (int i = st(br); i <= r; i++) a[i] += c, sum[br] += c;
for (int i = bl + 1; i <= br - 1; i++) add[i] += c;
}
}
LL query(int l, int r, LL c) {
int bl = pos[l], br = pos[r];
LL res = 0;
if (bl == br)
for (int i = l; i <= r; i++) res = (res + a[i] + add[bl]) % c;
else {
for (int i = l; i <= en(bl); i++) res = (res + a[i] + add[bl]) % c;
for (int i = st(br); i <= r; i++) res = (res + a[i] + add[br]) % c;
for (int i = bl + 1; i <= br - 1; i++) res = (res + sum[i] + add[i] * block) % c;
}
return res;
}
int main() {
n = gi();
block = (int)(sqrt(n) + 0.5);
for (int i = 1; i <= n; i++) a[i] = gll();
for (int i = 1; i <= n; i++) pos[i] = (i - 1) / block + 1, sum[pos[i]] += a[i];
for (int cas = 1; cas <= n; cas++) {
int opt = gi(), l = gi(), r = gi();
LL c = gi();
if (opt == 0)
update(l, r, c);
else
printf("%lld\n", query(l, r, c + 1) % (c + 1));
}
return 0;
}

# 数列分块5

## ac代码

#include <bits/stdc++.h>
#define ms(a, b) memset(a, b, sizeof(a))
#define LL long long
using namespace std;
inline int gi() {
int w = 0, x = 0;
char ch = 0;
while (!isdigit(ch)) w |= ch == '-', ch = getchar();
while (isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
return w ? -x : x;
}
int block, n;
#define st(x) (x * block - block + 1)
#define en(x) (x * block)
#define N 50005
int fg[N], a[N], pos[N], sum[N];
void update(int l, int r) {
int bl = pos[l], br = pos[r];
if (bl == br)
for (int i = l; i <= r; i++) {
sum[bl] -= a[i];
a[i] = sqrt(a[i]);
sum[bl] += a[i];
}
else {
for (int i = l; i <= en(bl); i++) {
sum[bl] -= a[i];
a[i] = sqrt(a[i]);
sum[bl] += a[i];
}
for (int i = st(br); i <= r; i++) {
sum[br] -= a[i];
a[i] = sqrt(a[i]);
sum[br] += a[i];
}
for (int i = bl + 1; i <= br - 1; i++) {
if (fg[i])
continue;
sum[i] = 0;
fg[i] = 1;
for (int j = st(i); j <= en(i); j++) {
a[j] = sqrt(a[j]);
sum[i] += a[j];
if (a[j] > 1)
fg[i] = 0;
}
}
}
}
int query(int l, int r) {
int bl = pos[l], br = pos[r], res = 0;
if (bl == br)
for (int i = l; i <= r; i++) res += a[i];
else {
for (int i = l; i <= en(bl); i++) res += a[i];
for (int i = st(br); i <= r; i++) res += a[i];
for (int i = bl + 1; i <= br - 1; i++) res += sum[i];
}
return res;
}
int main() {
ms(fg, 0);
n = gi();
block = (int)(sqrt(n) + 0.5);
for (int i = 1; i <= n; i++) a[i] = gi(), pos[i] = (i - 1) / block + 1, sum[pos[i]] += a[i];
for (int cas = 1; cas <= n; cas++) {
int opt = gi(), l = gi(), r = gi(), c = gi();
if (opt == 0)
update(l, r);
else
printf("%d\n", query(l, r));
}
return 0;
}

# 数列分块6

## ac代码

#include <bits/stdc++.h>
#define ms(a, b) memset(a, b, sizeof(a))
#define pb push_back
#define LL long long
#define pii pair<int, int>
#define Mp make_pair
#define fi first
#define se second
using namespace std;
inline int gi() {
int w = 0, x = 0;
char ch = 0;
while (!isdigit(ch)) w |= ch == '-', ch = getchar();
while (isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
return w ? -x : x;
}
#define N 100005
vector<int> v[705];
int a[N];
int n, sum, block;
pii query(int r) {
int x = 1;
while (r > (int)v[x].size()) r -= v[x].size(), x++;
return Mp(x, r - 1);
}
void repart() {
vector<int> kkk;
kkk.clear();
for (int i = 1; i <= 705; i++) {
if (v[i].size() == 0)
break;
for (int j = 0; j < (int)v[i].size(); j++) kkk.pb(v[i][j]);
v[i].clear();
}
block = (int)(sqrt(n) + 0.5);
for (int i = 1; i <= sum; i++) v[(i - 1) / block + 1].pb(kkk[i - 1]);
}
void insert(int l, int c) {
pii pos = query(l);
v[pos.fi].insert(v[pos.fi].begin() + pos.se, c);
}
int main() {
n = gi();
block = (int)(sqrt(n) + 0.5);
for (int i = 1; i <= n; i++) v[(i - 1) / block + 1].pb(a[i] = gi());
int cnt = 0, limit = block;
sum = n;
for (int cas = 1; cas <= n; cas++) {
++cnt;
if (cnt == 10 * limit)
repart();
int opt = gi(), l = gi(), r = gi(), c = gi();
if (opt == 0)
insert(l, r), sum++;
else {
pii ans = query(r);
printf("%d\n", v[ans.fi][ans.se]);
}
}
return 0;
}

# 数列分块7

## 分析

• 乘法：$(x \times mul+add)\times new$也就是$x\times mul \times new+add \times new$
• 加法：$x \times mul+add+new$
根据上面的式子，更新懒标记就可以了

## ac代码

#include <bits/stdc++.h>
#define ms(a, b) memset(a, b, sizeof(a))
#define LL long long
using namespace std;
inline int gi() {
int w = 0, x = 0;
char ch = 0;
while (!isdigit(ch)) w |= ch == '-', ch = getchar();
while (isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
return w ? -x : x;
}
int block, n;
#define N 100005
#define mod 10007
#define st(x) (block * x - block + 1)
#define en(x) (block * x)
int mul[N], add[N], a[N], pos[N];
void pushdown(int x) {
if (add[x] == 0 && mul[x] == 1)
return;
for (int i = st(x); i <= en(x); i++) a[i] = ((a[i] * mul[x]) % mod + add[x]) % mod;
add[x] = 0;
mul[x] = 1;
}
void update_add(int l, int r, int c) {
int bl = pos[l], br = pos[r];
pushdown(bl);
pushdown(br);
if (bl == br)
for (int i = l; i <= r; i++) a[i] = (a[i] + c) % mod;
else {
for (int i = l; i <= en(bl); i++) a[i] = (a[i] + c) % mod;
for (int i = st(br); i <= r; i++) a[i] = (a[i] + c) % mod;
for (int i = bl + 1; i < br; i++) add[i] = (add[i] + c) % mod;
}
}
void update_mul(int l, int r, int c) {
int bl = pos[l], br = pos[r];
pushdown(bl), pushdown(br);
if (bl == br)
for (int i = l; i <= r; i++) a[i] = (a[i] * c) % mod;
else {
for (int i = l; i <= en(bl); i++) a[i] = (a[i] * c) % mod;
for (int i = st(br); i <= r; i++) a[i] = (a[i] * c) % mod;
for (int i = bl + 1; i < br; i++) mul[i] = (mul[i] * c) % mod, add[i] = (add[i] * c) % mod;
}
}
int main() {
n = gi();
block = sqrt(n);
for (int i = 1; i <= n; i++) a[i] = gi();
for (int i = 1; i <= n; i++) pos[i] = (i - 1) / block + 1;
for (int i = 1; i <= pos[n]; i++) mul[i] = 1, add[i] = 0;
for (int cas = 1; cas <= n; cas++) {
int opt = gi(), l = gi(), r = gi(), c = gi();
if (opt == 0)
update_add(l, r, c);
else if (opt == 1)
update_mul(l, r, c);
else
printf("%d\n", ((a[r] * mul[pos[r]]) + add[pos[r]]) % mod);
}
return 0;
}

# 数列分块8

## ac代码

#include <bits/stdc++.h>
#define ms(a, b) memset(a, b, sizeof(a))
#define pb push_back
#define LL long long
using namespace std;
inline int gi() {
int w = 0, x = 0;
char ch = 0;
while (!isdigit(ch)) w |= ch == '-', ch = getchar();
while (isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
return w ? -x : x;
}
int n, block;
#define N 100005
#define st(x) (block * x - block + 1)
#define en(x) (block * x)
int tag[N], pos[N], a[N];
void pushdown(int x) {
if (tag[x] == -1)
return;
for (int i = st(x); i <= en(x); i++) a[i] = tag[x];
tag[x] = -1;
}
int solve(int l, int r, int c) {
int bl = pos[l], br = pos[r], res = 0;
pushdown(bl);
pushdown(br);
if (bl == br)
for (int i = l; i <= r; i++) (a[i] == c) ? res++ : a[i] = c;
else {
for (int i = l; i <= en(bl); i++) (a[i] == c) ? res++ : a[i] = c;
for (int i = st(br); i <= r; i++) (a[i] == c) ? res++ : a[i] = c;
for (int i = bl + 1; i < br; i++) {
if (tag[i] != -1)
(tag[i] != c) ? tag[i] = c : res += block;
else {
for (int j = st(i); j <= en(i); j++) (c == a[j]) ? res++ : a[j] = c;
tag[i] = c;
}
}
}
return res;
}
int main() {
n = gi();
block = sqrt(n);
for (int i = 1; i <= n; i++) a[i] = gi(), pos[i] = (i - 1) / block + 1;
for (int i = 1; i <= pos[n]; i++) tag[i] = -1;
for (int cas = 1; cas <= n; cas++) {
int l = gi(), r = gi(), c = gi();
printf("%d\n", solve(l, r, c));
}
return 0;
}

# 数列分块9

## ac代码（好久之前打的，码风有一点不一样）

#include <iostream>
#include <stack>
#include <stdio.h>
#include <cmath>
#include <vector>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;
#define ll long long
const int maxn = 2e5 + 100;
vector<int> q[maxn];
vector<int> vis;
int belong[maxn], a[maxn];
int num[maxn];
int dp[2500][2500];
int n, block = 50;
void init(int x) {
memset(num, 0, sizeof(num));
int maxx = 0, ans = 0;
for (int i = (x - 1) * block + 1; i <= n; i++) {
num[a[i]]++;
if (num[a[i]] > maxx || (num[a[i]] == maxx && ans > a[i])) {
maxx = num[a[i]];
ans = a[i];
}
dp[x][belong[i]] = ans;
}
}
int cal(int st, int ed, int num) {
return upper_bound(q[num].begin(), q[num].end(), ed) - lower_bound(q[num].begin(), q[num].end(), st);
}
int ask(int st, int ed) {
int maxx = 0, ans = 0;
if (belong[st] == belong[ed]) {
for (int i = st; i <= ed; i++) {
int tmp = cal(st, ed, a[i]);
if (maxx < tmp || (maxx == tmp && ans > a[i])) {
ans = a[i];
maxx = tmp;
}
}
return ans;
}
for (int i = st; i <= min(ed, (belong[st] * block)); i++) {
int tmp = cal(st, ed, a[i]);
if (maxx < tmp || (maxx == tmp && ans > a[i])) {
ans = a[i];
maxx = tmp;
}
}
for (int i = (belong[ed] - 1) * block + 1; i <= ed; i++) {
int tmp = cal(st, ed, a[i]);
if (maxx < tmp || (maxx == tmp && ans > a[i])) {
ans = a[i];
maxx = tmp;
}
}
int tmp = cal(st, ed, dp[belong[st] + 1][belong[ed] - 1]);
if (maxx < tmp || (maxx == tmp && ans > dp[belong[st] + 1][belong[ed] - 1])) {
ans = dp[belong[st] + 1][belong[ed] - 1];
maxx = tmp;
}
return ans;
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
vis.push_back(a[i]);
belong[i] = (i - 1) / block + 1;
}
sort(vis.begin(), vis.end());
vis.erase(unique(vis.begin(), vis.end()), vis.end());
for (int i = 1; i <= n; i++) {
a[i] = lower_bound(vis.begin(), vis.end(), a[i]) - vis.begin();
}
for (int i = 1; i <= belong[n]; i++) {
init(i);
}
for (int i = 1; i <= n; i++) {
q[a[i]].push_back(i);
}
int Case = n, st, ed;
while (Case--) {
scanf("%d %d", &st, &ed);
printf("%d\n", vis[ask(st, ed)]);
}
return 0;
}
posted @ 2019-03-14 18:58 chhokmah 阅读(...) 评论(...) 编辑 收藏