bzoj4241 历史研究
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4241
【题解】
和作诗相似。
f[i,j]表示块i到块j的答案。
g[i,j]表示1...i块中j出现次数。
那么分块直接做即可。
复杂度O(n根号n)
跑的好慢啊。。
# 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; }