回滚莫队 …
就是说对于这题来说,添加容易,但是删除困难,那么就不考虑删除,即把左右端点分别放在块的两边,中间的是可以直接处理出来,然后块中的暴力更新,完了以后再变更为更新前的状态即可.
复杂度
O(nn‾√)
O
(
n
n
)
c++代码如下:
#include<bits/stdc++.h>
#define rep(i,x,y) for(register int i = x ; i <= (y); ++ i )
#define repd(i,x,y) for(register int i = x ; i >= (y); -- i )
using namespace std;
typedef long long ll;
template<typename T>inline void read(T&x)
{
char c;int sign = 1;x = 0;
do { c = getchar(); if(c == '-') sign = -1; }while(!isdigit(c));
do { x = x * 10 + c - '0'; c = getchar(); }while(isdigit(c));
x *= sign;
}
const int N = 1e5+50;
int n,m,id[N],num[N],belong[N]; ll mx,cnt,ans[N],a[N],w[N];
struct DATA { int l,r,id; }Q[N];
const bool cmp(DATA a,DATA b) { return belong[a.l] < belong[b.l] || belong[a.l] == belong[b.l] && belong[a.r] < belong[b.r]; }
int main()
{
read(n); read(m);
rep(i,1,n) read(a[i]),w[i] = a[i];
rep(i,1,m) read(Q[i].l), read(Q[i].r), Q[i].id = i;
int d = (int)sqrt(n);
sort(w + 1,w + 1 + n);
rep(i,1,n) id[i] = lower_bound(w+1,w+1+n,a[i]) - w;
rep(i,1,n) belong[i] = (i / d) +1;
sort(Q + 1, Q + 1 + m , cmp);
int l,r;
rep(j,1,m)
{
if(belong[Q[j].l] != belong[Q[j-1].l])
{
memset(num,0,sizeof num),cnt = 0;
l = Q[j].l;
while(belong[l+1] == belong[l])
++l;
r = l - 1;
}
if(belong[Q[j].l] == belong[Q[j].r])
{
mx = 0;
rep(i,Q[j].l,Q[j].r)
{
++num[id[i]];
mx = max(num[id[i]] * a[i],mx);
}
rep(i,Q[j].l,Q[j].r)
--num[id[i]];
ans[Q[j].id] = mx;
continue;
}
while(belong[r] != belong[Q[j].r])
{
++r;
++num[id[r]];
cnt = max(cnt,num[id[r]] * a[r]);
}
mx = cnt;
rep(i,Q[j].l,l-1)
{
++num[id[i]];
mx = max(num[id[i]] * a[i],mx);
}
rep(i,r+1,Q[j].r)
{
++num[id[i]];
mx = max(num[id[i]] * a[i],mx);
}
rep(i,r+1,Q[j].r) --num[id[i]];
rep(i,Q[j].l,l-1) --num[id[i]];
ans[Q[j].id] = mx;
}
rep(i,1,m) printf("%lld\n",ans[i]) ;
return 0;
}