莫队+套路值域分块。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
const int len=305;
int n,m,a[maxn],cnt[maxn],sum[maxn],ans[maxn];
int laz[maxn],anss[maxn],lft[maxn],rht[maxn];
inline int read(){
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
return x*f;
}
struct node{
int l,r,a,b,bl,id;
}q[maxn];
inline int cmp(node x,node y){
return x.bl==y.bl?x.r<y.r:x.bl<y.bl;
}
inline int query(int x,int y){
int tot=0;
for(int i=x;i<=y&&i<=rht[x/len];i++)
tot+=cnt[i];
if(y<=rht[x/len])return tot;
for(int i=x/len+1;rht[i]<y;i++)
tot+=sum[i];
for(int i=lft[y/len];i<=y;i++)
tot+=cnt[i];
return tot;
}
inline int quest(int x,int y){
int tot=0;
for(int i=x;i<=y&&i<=rht[x/len];i++)
if(cnt[i])tot++;
if(y<=rht[x/len])return tot;
for(int i=x/len+1;rht[i]<y;i++)
tot+=laz[i];
for(int i=lft[y/len];i<=y;i++)
if(cnt[i])tot++;
return tot;
}
inline void del(int x){
cnt[a[x]]--;
sum[a[x]/len]--;
laz[a[x]/len]-=!cnt[a[x]];
}
inline void add(int x){
laz[a[x]/len]+=!cnt[a[x]];
cnt[a[x]]++;
sum[a[x]/len]++;
}
int main(){
n=read(),m=read();
for(int i=1;i<=n;i++)
a[i]=read();
for(int i=0;i<=350;i++){
lft[i]=i*len;
rht[i]=(i+1)*len-1;
}
for(int i=1;i<=m;i++){
q[i].id=i;
q[i].l=read(),q[i].r=read();
q[i].a=read(),q[i].b=read();
q[i].bl=q[i].l/len;
}
sort(q+1,q+1+m,cmp);
int l=1,r=0;
for(int i=1;i<=m;i++){
while(l<q[i].l)del(l++);
while(l>q[i].l)add(--l);
while(r<q[i].r)add(++r);
while(r>q[i].r)del(r--);
ans[q[i].id]=query(q[i].a,q[i].b);
anss[q[i].id]=quest(q[i].a,q[i].b);
}
for(int i=1;i<=m;i++)
printf("%d %d
",ans[i],anss[i]);
return 0;
}
深深地感到自己的弱小。