用莫队比直接做快了很多。。
#include<iostream> #include<cstring> #include<cstdio> #include<cmath> using namespace std; #include<algorithm> #define maxn 100005 int a[maxn],b[maxn],c[maxn],num[maxn];//原始数组,排序后的数组,离散后的数组,离散后的数组中元素出现的次数 int s;//块长度 struct Query{ int l,r,id; bool operator<(const Query &a)const{ if(l/s==a.l/s) return r<a.r; return l/s<a.l/s; } }q[maxn]; int ans[maxn]; int main(){ int n,m; while(scanf("%d%d",&n,&m)==2){ s=(int)sqrt(1.0*n); for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i]; sort(b+1,b+n+1); for(int i=1;i<=n;i++) c[i]=lower_bound(b+1,b+1+n,a[i])-b; for(int i=1;i<=m;i++) scanf("%d%d",&q[i].l,&q[i].r),q[i].id=i; sort(q+1,q+m+1); //处理每个询问 int l=1,r=0,tmp=0; for(int i=1;i<=m;i++){ while(r<q[i].r){//右边界拓展 r++; if(num[c[r]]==a[r]-1) tmp++; else if(num[c[r]]==a[r]) tmp--; num[c[r]]++; } while(r>q[i].r){//右边界往回缩 if(num[c[r]]==a[r]) tmp--; else if(num[c[r]]==a[r]+1) tmp++; num[c[r]]--; r--; } while(l<q[i].l){//左边界往回缩 if(num[c[l]]==a[l]) tmp--; else if(num[c[l]]==a[l]+1) tmp++; num[c[l]]--; l++; } while(l>q[i].l){//左边界拓展 l--; if(num[c[l]]==a[l]-1) tmp++; else if(num[c[l]]==a[l]) tmp--; num[c[l]]++; } ans[q[i].id]=tmp; } for(int i=1;i<=m;i++) printf("%d ",ans[i]); } return 0; }