这是一道套路题,不过我现在才学会套路。
对于莫队算法,进队统计答案很快,出队统计答案很慢的情况有一个套路:把所有的出队变成进队,每次询问的[l,r],把l放到l所在的块的末尾为l’,然后把l到l’-1的都入队,更新答案,因为右端点是递增的,所以右边就逐个进队就好了,然后结束的时候就把l’到l-1退队。每次l换块的时候,就把所有的数据暴力重构。
#include
#include
#include
#include
#include
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
const int maxn=100007;
typedef long long ll;
int i,j,k,l,t,n,m,da,kuai[maxn],r,num,g[maxn],d[maxn],tot;
ll ans2,ans,ans1[maxn];
int c[maxn];
struct node{
int a,b,c;
}b[maxn],q[maxn];
struct nod{
int x,y;
}a[maxn];
bool cmp(node x,node y){
return kuai[x.a]y.a]||kuai[x.a]==kuai[y.a]&&x.b<y.b;
}
bool cmp1(nod x,nod y){
return x.x<y.x;
}
bool cmp2(node x,node y){
return x.a<y.a||x.a==y.a&&x.b<y.b;
}
void jin(int x){
c[g[x]]++;
if((ll)d[g[x]]*c[g[x]]>ans)ans=(ll)d[g[x]]*c[g[x]];
}
void chu(int x){
c[g[x]]--;
/* int i;
fo(i,1,num){
ans=max(d[g[i]]*c[g[i]],ans);
}*/
}
int main(){
// freopen("fan.in","r",stdin);
// freopen("fan.out","w",stdout);
scanf("%d%d",&n,&m);
da=sqrt(n);
fo(i,1,n)scanf("%d",&a[i].x),a[i].y=i,kuai[i]=(i-1)/da+1;
sort(a+1,a+1+n,cmp1);
d[++num]=a[1].x;g[a[1].y]=1;
fo(i,2,n){
if(a[i].x!=a[i-1].x){
d[++num]=a[i].x,g[a[i].y]=num;
}
else g[a[i].y]=num;
}
fo(i,1,m){
scanf("%d%d",&b[i].a,&b[i].b);b[i].c=i;
}
sort(b+1,b+1+m,cmp);
l=0;
fo(j,1,m){
if(b[j].a==b[j].b){
q[++tot].a=b[j].a;
q[tot].b=b[j].b;
q[tot].c=b[j].c;
continue;
}
if(kuai[l]!=kuai[b[j].a]){
ans=0;
fo(i,1,num)c[i]=0;
l=kuai[b[j].a]*da,r=b[j].b;
fo(i,l,r)jin(i);
ans2=ans;
}
ans=ans2;l=kuai[b[j].a]*da;
while(rwhile(l>b[j].a)jin(--l);ans1[b[j].c]=ans;
fo(i,b[j].a,kuai[b[j].a]*da-1)chu(i);
}
sort(q+1,q+1+tot,cmp2);
l=0;
fo(j,1,m){
if(l<q[j].a){
ans=0;
fo(i,1,num)c[i]=0;
l=q[j].a,r=q[j].b;
fo(i,l,r)jin(i);
}
else{
fo(i,r+1,q[j].b)jin(i);
}
ans1[q[j].c]=ans;
}
fo(i,1,m)printf("%lld\n",ans1[i]);
}