一个长度为 $n$ 的序列,$q$ 次询问,给定 $[l,r]$,求最大的 $a \times (a 在 [l,r] 中出现次数)$
$n,q \leq 100000$
sol:
莫队,这道题加入一个数很容易,但不是很好删除一个数,所以我们魔改一下莫队的处理方式
具体地:
1.对于长度小于 $\sqrt{n}$ 的询问,暴力
2.每次对于一个块,处理左端点在这个块里的询问,对于每次询问,先把 $L$ 指针设为块的右端点,向右移动 $R$ 指针,求出这组询问答案没移动左端点时的结果,然后把 $L$ 往左移求出答案,这组询问求完之后把答案和 $cnt$ 数组恢复成没移动左端点时的结果
这样是 $O(n\sqrt{n})$ 的
跑不过分块 QAQ
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include <bits/stdc++.h> #define LL long long #define rep(i, s, t) for (register int i = (s), i##end = (t); i <= i##end; ++i) #define dwn(i, s, t) for (register int i = (s), i##end = (t); i >= i##end; --i) using namespace std; namespace IO{ const int BS=(1<<23)+5; int Top=0; char Buffer[BS],OT[BS],*OS=OT,*HD,*TL,SS[30]; const char *fin=OT+BS-1; char Getchar(){if(HD==TL){TL=(HD=Buffer)+fread(Buffer,1,BS,stdin);} return (HD==TL)?EOF:*HD++;} void flush(){fwrite(OT,1,OS-OT,stdout);} void Putchar(char c){*OS++ =c;if(OS==fin)flush(),OS=OT;} void write(LL x){ if(!x){Putchar('0');return;} if(x<0) x=-x,Putchar('-'); while(x) SS[++Top]=x%10,x/=10; while(Top) Putchar(SS[Top]+'0'),--Top; } int read(){ int nm=0,fh=1; char cw=Getchar(); for(;!isdigit(cw);cw=Getchar()) if(cw=='-') fh=-fh; for(;isdigit(cw);cw=Getchar()) nm=nm*10+(cw-'0'); return nm*fh; } } using namespace IO; const int maxn = 100100; int n, q, pos = 1, SZ; int a[maxn], v[maxn], cnt[maxn]; int bl[maxn]; LL ans[maxn]; struct Ques { int l, r, id; Ques(){} Ques(int _1, int _2, int _3) : l(_1), r(_2), id(_3){} inline bool operator < (const Ques &b) const { return bl[l] == bl[b.l] ? r < b.r : l < b.l; } }qs[maxn]; int force_cnt[maxn]; inline LL force(int l, int r) { LL ret = 0; rep(i, l, r) force_cnt[a[i]] = 0; rep(i, l, r) force_cnt[a[i]]++; rep(i, l, r) ret = max(ret, 1LL * force_cnt[a[i]] * v[a[i]]); return ret; } inline void modify(int &i, int pos) { int L = min(n, SZ * pos); int ql = L + 1, qr = L; LL tmp = 0; memset(cnt, 0, sizeof(cnt)); for(; bl[qs[i].l] == pos; i++) { if(bl[qs[i].l] == bl[qs[i].r]) ans[qs[i].id] = force(qs[i].l, qs[i].r); else { while(qr < qs[i].r) { qr++; cnt[a[qr]]++; tmp = max(tmp, 1LL * v[a[qr]] * cnt[a[qr]]); } LL tans = tmp; while(ql > qs[i].l) { --ql; cnt[a[ql]]++; tmp = max(tmp, 1LL * v[a[ql]] * cnt[a[ql]]); } ans[qs[i].id] = tmp; while(ql < L + 1) { cnt[a[ql]]--; ql++; } tmp = tans; } } } int main() { // freopen("2.in","r",stdin); // freopen("buff.out","w",stdout); n = read(); q = read(); SZ = sqrt(n); rep(i, 1, n) v[i] = a[i] = read(), bl[i] = (i-1) / SZ + 1; sort(v + 1, v + n + 1); rep(i, 1, n) a[i] = lower_bound(v + 1, v + n + 1, a[i]) - v; rep(i, 1, q) { int l = read(), r = read(); qs[i] = Ques(l, r, i); } sort(qs + 1, qs + q + 1); rep(i, 1, bl[n]) modify(pos, i); rep(i, 1, q) write(ans[i]), Putchar('\n'); flush(); }