长度为n的序列a,
定义区间内一个数的价值为 数值*出现次数,问区间内的数的最大价值是多少。
m个询问,每个询问给出 [ l , r ] [l,r] [l,r],问区间内数的最大价值。
1 < = n , m < = 1 0 5 , 1 < = a i < = 1 0 9 1<=n,m<=10^5,1<=a_i<=10^9 1<=n,m<=105,1<=ai<=109
引入一个大佬的博客:
这题也是一个回滚莫队的裸题,直接上就完事了
#include
#define rep(i, st, ed) for (int i = st; i <= ed; i++)
#define rwp(i, ed, st) for (int i = ed; i >= st; i--)
#define N 100005
using namespace std;
typedef long long ll;
struct Node {
int l, r, id;
}q[N];
int beln[N], sum[N], val[N], cdp[N], cnt[N], al[N], ar[N], d[N], n, m, siz, num;
ll ans[N];
void read(int &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = - 1; s = getchar(); }
while (s >= '0' && s <= '9') { x = x * 10 + (s - '0'); s = getchar(); }
x = x * f;
}
int cmp(Node aa, Node bb) {
return (beln[aa.l] ^ beln[bb.l]) ? beln[aa.l] < beln[bb.l] : aa.r < bb.r;
}
void write(ll x) {
if (x > 9) write(x / 10);
putchar(x % 10 + '0');
}
int main() {
read(n), read(m);
siz = sqrt(n);
num = (int)ceil((double)n / siz);
rep(i, 1, num) {
al[i] = siz * (i - 1) + 1, ar[i] = siz * i;
rep(j, al[i], ar[i]) beln[j] = i;
}
ar[num] = n;
rep(i, 1, n) read(val[i]), d[i] = val[i];
sort(d + 1, d + n + 1);
int tot = unique(d + 1, d + n + 1) - d - 1;
rep(i, 1, n) cdp[i] = lower_bound(d + 1, d + tot + 1, val[i]) - d;
rep(i, 1, m) read(q[i].l), read(q[i].r), q[i].id = i;
sort(q + 1, q + m + 1, cmp);
int i = 1;
rep(k, 0, num) {
int l = ar[k] + 1, r = ar[k];
ll now = 0;
memset(cnt, 0, sizeof(cnt));
for (; beln[q[i].l] == k; i++) {
int L = q[i].l, R = q[i].r;
ll tmp = 0;
if (beln[L] == beln[R]) {
rep(j, L, R) sum[cdp[j]] = 0;
rep(j, L, R) ++sum[cdp[j]], tmp = max(tmp, 1ll * sum[cdp[j]] * val[j]);
ans[q[i].id] = tmp;
continue;
}
while (r < R) ++r, ++cnt[cdp[r]], now = max(now, 1ll * cnt[cdp[r]] * val[r]);
tmp = now;
while (l > L) --l, ++cnt[cdp[l]], now = max(now, 1ll * cnt[cdp[l]] * val[l]);
ans[q[i].id] = now;
while (l < ar[k] + 1) --cnt[cdp[l]], ++l;
now = tmp;
}
if (i > m) break;
}
rep(i, 1, m) write(ans[i]), printf("\n");
return 0;
}