題目連接php
經典大分塊..不過挺好寫的。就寫了半個小時左右。
處理出數組
預處理這兩個數組都離散化後利用一個桶就能夠了。
考慮每一個詢問\([l,r]\)的答案可能的來源,首先確定\(ans[l][r]\)是其中的一個候選項,而後兩個邊界塊中的數也都是可能的候選項。那麼枚舉這兩個塊中的數,利用\(cnt\)數組和一個桶便可解決。
複雜度\(O(n \sqrt{n})\)spa
#include <cmath> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int N = 100010; const int M = 320; inline void read(int &x) { x = 0; char c = getchar(); while(c < '0' || c > '9') c = getchar(); while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); } } ll ans[M][M]; int bl[N], L[M], R[M], cnt[M][N]; int a[N], b[N], c[N], tong[N]; int n, m, block, siz; void init() { siz = sqrt(n); block = n / siz; if(n % siz) ++block; for(int i = 1; i <= n; ++i) { bl[i] = (i - 1) / siz + 1; } for(int i = 1; i <= block; ++i) { L[i] = (i - 1) * siz + 1; R[i] = i * siz; } R[block] = n; for(int i = 1; i <= block; ++i) { for(int j = L[i]; j <= R[i]; ++j) cnt[i][a[j]]++; } for(int j = 1; j <= n; ++j) for(int i = 1; i <= block; ++i) cnt[i][j] += cnt[i - 1][j]; for(int i = 1; i <= block; ++i) { for(int k = L[i]; k <= R[i]; ++k) { tong[a[k]]++; ans[i][i] = max(ans[i][i], 1ll * tong[a[k]] * c[k]); } for(int j = i + 1; j <= block; ++j) { ans[i][j] = ans[i][j - 1]; for(int k = L[j]; k <= R[j]; ++k) { tong[a[k]]++; ans[i][j] = max(ans[i][j], 1ll * tong[a[k]] * c[k]); } } for(int j = L[i]; j <= n; ++j) tong[a[j]] = 0; } } ll solve(int l, int r) { ll Ans = 0; if(bl[l] == bl[r] || bl[r] == bl[l] + 1) { for(int i = l; i <= r; ++i) { tong[a[i]]++; Ans = max(Ans, 1ll * tong[a[i]] * c[i]); } for(int i = l; i <= r; ++i) tong[a[i]] = 0; return Ans; } Ans = ans[bl[l] + 1][bl[r] - 1]; for(int i = l; i <= R[bl[l]]; ++i) { tong[a[i]]++; Ans = max(Ans, 1ll * (tong[a[i]] + cnt[bl[r] - 1][a[i]] - cnt[bl[l]][a[i]]) * c[i]); } for(int i = L[bl[r]]; i <= r; ++i) { tong[a[i]]++; Ans = max(Ans, 1ll * (tong[a[i]] + cnt[bl[r] - 1][a[i]] - cnt[bl[l]][a[i]]) * c[i]); } for(int i = l; i <= R[bl[l]]; ++i) tong[a[i]] = 0; for(int i = L[bl[r]]; i <= r; ++i) tong[a[i]] = 0; return Ans; } int main() { #ifndef ONLINE_JUDGE freopen("data.in","r",stdin); #endif read(n); read(m); for(int i = 1; i <= n; ++i) { read(a[i]); b[i] = c[i] = a[i]; } sort(b + 1, b + n + 1); for(int i = 1; i <= n; ++i) a[i] = lower_bound(b + 1, b + n + 1, a[i]) - b; init(); while(m--) { int l, r; read(l); read(r); printf("%lld\n", solve(l, r)); } }