给出 n 个整数 \(x_1, x_2, ...,x_n\) ,询问 [l, r] 中 max{\(x_k\times cnt_{x_k}\)}( \(cnt_i\) 表示 i 出现的次数)
分析
回滚莫队裸题。
当然也可以用分块做,但我一开始打的分块,成功的只过了 4 个点......没调出来......
顺便贴一下官方题解,虽然是日文
代码
回滚莫队
//========================= // author:hliwen // date:2020.1.17 //========================= #include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define N 100005 #define il inline #define re register #define DEBUG puts("ok") #define tie0 cin.tie(0),cout.tie(0) #define fastio ios::sync_with_stdio(false) #define File(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout) using namespace std; typedef long long ll; template <typename T> inline void read(T &x) { T f = 1; x = 0; char c; for (c = getchar(); !isdigit(c); c = getchar()) if (c == '-') f = -1; for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48); x *= f; } int n, m, q, sz; int bl[N], L[N], R[N], id[N], cnt[N], tot[N]; ll t[N], hs[N], ans[N]; struct query { int l, r, id; friend bool operator < (query x, query y) { return (bl[x.l] ^ bl[y.l]) ? bl[x.l] < bl[y.l] : x.r < y.r; } } qy[N]; int main() { read(n), read(q); sz = sqrt(n); for (int i = 1; i <= n; ++i) { read(t[i]), hs[i] = t[i]; bl[i] = (i - 1) / sz + 1; } m = bl[n]; for (int i = 1; i <= m; ++i) { L[i] = (i - 1) * sz + 1; R[i] = i * sz; } sort(hs + 1, hs + 1 + n); int num = unique(hs + 1, hs + 1 + n) - hs - 1; for (int i = 1; i <= n; ++i) id[i] = lower_bound(hs + 1, hs + 1 + num, t[i]) - hs; for (int i = 1; i <= q; ++i) { read(qy[i].l), read(qy[i].r); qy[i].id = i; } sort(qy + 1, qy + 1 + q); int i = 1; for (int k = 0; k <= m; ++k) { int l = R[k] + 1, r = R[k]; ll now = 0; memset(cnt, 0, sizeof cnt); for ( ; bl[qy[i].l] == k; ++i) { int ql = qy[i].l, qr =qy[i].r; ll tmp = 0; if (bl[ql] == bl[qr]) { for (int j = ql; j <= qr; ++j) tot[id[j]] = 0; for (int j = ql; j <= qr; ++j) { ++tot[id[j]]; tmp = max(tmp, 1ll * tot[id[j]] * t[j]); } ans[qy[i].id] = tmp; } else { while (r < qr) { ++cnt[id[++r]]; now = max(now, 1ll * cnt[id[r]] * t[r]); } tmp = now; while (l > ql) { ++cnt[id[--l]]; now = max(now, 1ll * cnt[id[l]] * t[l]); } ans[qy[i].id] = now; while (l < R[k] + 1) --cnt[id[l++]]; now = tmp; } } } for (int i = 1; i <= q; ++i) printf("%lld\n", ans[i]); return 0; }
官方正解
#include<stdio.h> #include<vector> #include<algorithm> #define SQ 100 /* bucket size: 100 */ using namespace std; int c[110000]; int d[110000]; int z[110000]; vector<int>v[110000]; long long e[110000]; long long f[3000][3000]; int main(){ int a,b; scanf("%d%d",&a,&b); for(int i=0;i<a;i++)scanf("%d",c+i); for(int i=0;i<a;i++){ z[i]=c[i]; } std::sort(z,z+a); for(int i=0;i<a;i++){ d[i]=lower_bound(z,z+a,c[i])-z; v[d[i]].push_back(i); } for(int i=0;i<a/SQ;i++){ for(int j=0;j<a;j++)e[j]=0LL; long long val=0LL; for(int j=i*SQ;j<=a;j++){ if(j%SQ==0){ f[i][j/SQ]=val; } e[d[j]]+=z[d[j]]; val=max(val,e[d[j]]); } } for(int i=0;i<b;i++){ int p,q; scanf("%d%d",&p,&q); p--; long long ret=f[(p+SQ-1)/SQ][q/SQ]; for(int j=p;j%SQ;j++){ ret=max(ret,(long long)z[d[j]]*(lower_bound(v[d[j]].begin(),v[d[j]].end(),q)-lower_bound(v[d[j]].begin(),v[d[j]].end(),p))); } for(int j=q-1;(j+1)%SQ;j--){ ret=max(ret,(long long)z[d[j]]*(lower_bound(v[d[j]].begin(),v[d[j]].end(),q)-lower_bound(v[d[j]].begin(),v[d[j]].end(),p))); } printf("%lld\n",ret); } }
我的错误分块代码
来源:https://www.cnblogs.com/hlw1/p/12207564.html