# bzoj4241 历史研究

【题解】

f[i,j]表示块i到块j的答案。

g[i,j]表示1...i块中j出现次数。

# include <vector>
# include <stdio.h>
# include <string.h>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 1e5 + 10, N = 360, BLOCK = 320;
const int mod = 1e9+7;

# define RG register
# define ST static

int n, q, B;
int a[M], bl[M];
int bst[N], bnd[N];
vector<int> ps;
int t[M];
ll f[N][N];
int g[N][M];

inline void prepare(int x) {
memset(t, 0, sizeof t);
int tem = x;
ll ans = 0;
for (int i=bst[x]; i<=n; ++i) {
++t[a[i]];
ans = max(ans, (ll)t[a[i]]*ps[a[i]-1]);
if(i == bnd[tem]) {
f[x][tem] = ans;
++tem;
}
}
}

int main() {
scanf("%d%d", &n, &q);
for (int i=1; i<=n; ++i) scanf("%d", a+i), ps.push_back(a[i]);
sort(ps.begin(), ps.end());
ps.erase(unique(ps.begin(), ps.end()), ps.end());
for (int i=1; i<=n; ++i) a[i] = lower_bound(ps.begin(), ps.end(), a[i]) - ps.begin() + 1;
for (int i=1; i<=n; ++i) bl[i] = (i-1)/BLOCK+1;
B = bl[n];
for (int i=1; i<=B; ++i) bst[i] = (i-1)*BLOCK+1, bnd[i] = min(n, i*BLOCK);
for (int i=1; i<=B; ++i) prepare(i);
for (int i=1; i<=B; ++i) {
for (int j=1; j<=n; ++j) g[i][j] = g[i-1][j];
for (int j=bst[i]; j<=bnd[i]; ++j) ++g[i][a[j]];
}
int l, r;
while(q--) {
scanf("%d%d", &l, &r);
if(bl[l] == bl[r]) {
ll ans = 0;
for (int i=l; i<=r; ++i) t[a[i]] = 0;
for (int i=l; i<=r; ++i) {
++t[a[i]];
ans = max(ans, (ll)t[a[i]]*ps[a[i]-1]);
}
printf("%lld\n", ans);
continue;
}
ll ans = 0;
if(bl[r]-bl[l] != 1) ans = f[bl[l]+1][bl[r]-1];
for (int i=l; i<=bnd[bl[l]]; ++i) t[a[i]] = g[bl[r]-1][a[i]] - g[bl[l]][a[i]];
for (int i=bst[bl[r]]; i<=r; ++i) t[a[i]] = g[bl[r]-1][a[i]] - g[bl[l]][a[i]];

for (int i=l; i<=bnd[bl[l]]; ++i) {
++t[a[i]];
ans = max(ans, (ll)t[a[i]]*ps[a[i]-1]);
}
for (int i=bst[bl[r]]; i<=r; ++i) {
++t[a[i]];
ans = max(ans, (ll)t[a[i]]*ps[a[i]-1]);
}
printf("%lld\n", ans);
}

return 0;
}
View Code

posted @ 2017-05-03 22:43  Galaxies  阅读(239)  评论(0编辑  收藏  举报