# BZOJ4241 历史研究

[传送门]

res[i][j] 表示第 $i$ 块到第 $j$ 块之间的答案，查询就先查询整块，再对两端暴力。

#include <bits/stdc++.h>
#define ll long long
using namespace std;

namespace IO {
const int MAXSIZE = 1 << 20;
char buf[MAXSIZE], *p1, *p2;
#define gc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, MAXSIZE, stdin), p1 == p2) ? EOF : *p1++)
template<typename T>
x = 0; T f = 1; char ch = gc();
while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = gc(); }
while (ch >= '0' && ch <= '9') { x = x * 10 + ch - 48; ch = gc(); }
x *= f;
}
} using namespace IO;

const int N = 1e5 + 7;
const int BLOCK = sqrt(N) + 7;

int n, q, a[N], v[N], tol;
int l[BLOCK], r[BLOCK], block, num, belong[N];
ll res[BLOCK][BLOCK], cnt[N], sum[BLOCK][N];

template<class T>
inline void checkmax(T &a, T b) {
if (a < b) a = b;
}

void build() {
block = sqrt(n);
num = n / block;
if (n % block) num++;
for (int i = 1; i <= num; i++)
l[i] = (i - 1) * block + 1, r[i] = i * block;
r[num] = n;
for (int i = 1; i <= num; i++)
for (int j = l[i]; j <= r[i]; j++)
belong[j] = i;
for (int i = 1; i <= num; i++) {
for (int j = 1; j <= tol; j++)
cnt[j] = 0, sum[i][j] = sum[i - 1][j];
ll mx = 0;
for (int j = l[i]; j <= n; j++) {
cnt[a[j]] += v[a[j]];
checkmax(mx, cnt[a[j]]);
res[i][belong[j]] = mx;
if (j <= r[i]) sum[i][a[j]] += v[a[j]];
}
}
for (int i = 1; i <= tol; i++)
cnt[i] = 0;
}

bool vis[N];

ll query(int x, int y) {
int p = belong[x], q = belong[y];
if (p == q) {
ll ans = 0;
for (int i = x; i <= y; i++)
cnt[a[i]] += v[a[i]], checkmax(ans, cnt[a[i]]);
for (int i = x; i <= y; i++)
cnt[a[i]] -= v[a[i]];
return ans;
}
ll ans = res[p + 1][q - 1];
if (p + 1 <= q - 1) {
for (int i = x; i <= r[p]; i++)
if (!vis[a[i]])
cnt[a[i]] += sum[q - 1][a[i]] - sum[p][a[i]], vis[a[i]] = 1;
for (int i = l[q]; i <= y; i++)
if (!vis[a[i]])
cnt[a[i]] += sum[q - 1][a[i]] - sum[p][a[i]], vis[a[i]] = 1;
}
for (int i = x; i <= r[p]; i++) {
cnt[a[i]] += v[a[i]];
checkmax(ans, cnt[a[i]]);
}
for (int i = l[q]; i <= y; i++) {
cnt[a[i]] += v[a[i]];
checkmax(ans, cnt[a[i]]);
}
for (int i = x; i <= r[p]; i++) {
cnt[a[i]] = 0;
vis[a[i]] = 0;
}
for (int i = l[q]; i <= y; i++) {
cnt[a[i]] = 0;
vis[a[i]] = 0;
}
return ans;
}

int main() {
for (int i = 1; i <= n; i++)
sort(v + 1, v + 1 + n);
tol = unique(v + 1, v + 1 + n) - v - 1;
for (int i = 1; i <= n; i++)
a[i] = lower_bound(v + 1, v + 1 + tol, a[i]) - v;
build();
for (int l, r; q--; ) {