Description
给你一个序列,对于一个区间,某一个值的价值为这个值出现的次数*这个值的权值,每次给一个询问,问这个区间内最大的价值。
Sample Input
5 5
9 8 7 8 9
1 2
3 4
4 4
1 4
2 4
Sample Output
9
8
8
16
16
分块套路题,没什么好说的。。。
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
int read() {
int s = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
return s * f;
}
bool v[110000];
int a[110000], b[110000], c[110000], d[110000];
int sum[320][110000], belong[110000], ll[320], rr[320];
int s[110000]; LL f[320][320];
int main() {
int n = read(), m = read();
for(int i = 1; i <= n; i++) a[i] = read(), b[i] = a[i];
sort(b + 1, b + n + 1);
for(int i = 1; i <= n; i++) c[i] = lower_bound(b + 1, b + n + 1, a[i]) - b, d[c[i]] = a[i];
int p = sqrt(n);
for(int i = 1; i <= n; i++) {
belong[i] = (i - 1) / p + 1;
if(belong[i] != belong[i - 1]) ll[belong[i]] = i, rr[belong[i - 1]] = i - 1;
} ll[1] = 1, rr[belong[n]] = n;
for(int i = 1; i <= belong[n]; i++) {
memset(s, 0, sizeof(s)); LL ans = 0;
for(int j = i; j <= belong[n]; j++) {
for(int k = ll[j]; k <= rr[j]; k++) {
s[c[k]]++;
if((LL)s[c[k]] * a[k] > ans) ans = (LL)s[c[k]] * a[k];
} f[i][j] = ans;
}
for(int j = ll[i]; j <= rr[i]; j++)
sum[i][c[j]]++;
} memset(s, 0, sizeof(s));
for(int i = 1; i <= belong[n]; i++) for(int j = 1; j <= n; j++) sum[i][j] += sum[i - 1][j];
for(int i = 1; i <= m; i++) {
int l = read(), r = read();
int bl = belong[l], br = belong[r];
LL ans = 0;
if(bl == br) {
for(int j = l; j <= r; j++) {
s[c[j]]++;
if((LL)s[c[j]] * a[j] > ans) ans = (LL)s[c[j]] * a[j];
} printf("%lld\n", ans);
for(int j = l; j <= r; j++) s[c[j]] = 0;
continue;
} ans = f[bl + 1][br - 1];
for(int j = l; j <= rr[bl]; j++) {
s[c[j]]++;
if(!v[c[j]]) {
v[c[j]] = 1;
s[c[j]] += sum[br - 1][c[j]] - sum[bl][c[j]];
} if((LL)s[c[j]] * a[j] > ans) ans = (LL)s[c[j]] * a[j];
}
for(int j = ll[br]; j <= r; j++) {
s[c[j]]++;
if(!v[c[j]]) {
v[c[j]] = 1;
s[c[j]] += sum[br - 1][c[j]] - sum[bl][c[j]];
} if((LL)s[c[j]] * a[j] > ans) ans = (LL)s[c[j]] * a[j];
} printf("%lld\n", ans);
for(int j = l; j <= rr[bl]; j++) s[c[j]] = 0, v[c[j]] = 0;
for(int j = ll[br]; j <= r; j++) s[c[j]] = 0, v[c[j]] = 0;
}
return 0;
}