对查询莫队处理,查询区间和分块处理。
复杂度O((n+m)n−√)
如果用莫队+BIT的话,复杂度是O(nn−√logn)
其实也是树套树裸题?O(mlog2n)
都应该过不去才对(划掉)
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 100010
inline char gc(){
static char buf[1<<16],*S,*T;
if(T==S){T=(S=buf)+fread(buf,1,1<<16,stdin);if(S==T) return EOF;}
return *S++;
}
inline int read(){
int x=0,f=1;char ch=gc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
return x*f;
}
int n,m,a[N],cnt[N],nn,bel[N],sum1[400],sum2[400],ans1[N*10],ans2[N*10];
bool inq[N];
struct quer{
int l,r,a,b,id;
friend bool operator<(quer a,quer b){return bel[a.l]==bel[b.l]?a.r<b.r:bel[a.l]<bel[b.l];}
}q[N*10];
inline void change(int p){
if(inq[p]){
sum1[bel[a[p]]]--;if(--cnt[a[p]]==0) sum2[bel[a[p]]]--;
}else{
sum1[bel[a[p]]]++;if(++cnt[a[p]]==1) sum2[bel[a[p]]]++;
}inq[p]^=1;
}
inline void ask(int x,int y,int id){
if(bel[x]==bel[y]){
for(int i=x;i<=y;++i) ans1[id]+=cnt[i],ans2[id]+=(cnt[i]?1:0);return;
}int r=min(bel[x]*nn,n);
for(int i=x;i<=r;++i) ans1[id]+=cnt[i],ans2[id]+=(cnt[i]?1:0);
for(int i=(bel[y]-1)*nn+1;i<=y;++i) ans1[id]+=cnt[i],ans2[id]+=(cnt[i]?1:0);
for(int i=bel[x]+1;i<bel[y];++i) ans1[id]+=sum1[i],ans2[id]+=sum2[i];
}
int main(){
// freopen("a.in","r",stdin);
n=read();m=read();nn=sqrt(n);
for(int i=1;i<=n;++i) a[i]=read(),bel[i]=(i-1)/nn+1;
for(int i=1;i<=m;++i) q[i].l=read(),q[i].r=read(),q[i].a=read(),q[i].b=read(),q[i].id=i;
sort(q+1,q+m+1);int l=1,r=0;
for(int i=1;i<=m;++i){
while(r>q[i].r) change(r--);
while(r<q[i].r) change(++r);
while(l<q[i].l) change(l++);
while(l>q[i].l) change(--l);
ask(q[i].a,q[i].b,q[i].id);
}for(int i=1;i<=m;++i) printf("%d %d\n",ans1[i],ans2[i]);
return 0;
}