莫队+值域分块。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define maxn 100050 #define maxm 1000050 using namespace std; int n,m,a[maxn],ans[maxm][3],pos[maxn],ret=316,st[maxn],tot=0; int cnt[maxn][5]; struct query { int l,r,a,b,id; }q[maxm]; bool cmp(const query &x,const query &y) { if (pos[x.l]!=pos[y.l]) return pos[x.l]<pos[y.l]; else return x.r<y.r; } int read() { char ch;int data=0; while (ch<'0' || ch>'9') ch=getchar(); while (ch>='0' && ch<='9') { data=data*10+ch-'0'; ch=getchar(); } return data; } void build() { tot=1; for (int i=1;i<=n;i++) { pos[i]=tot; if (!(i%ret)) st[tot++]=i; } if (n%ret) st[tot]=n;else tot--; } void modify(int x,int val) { int base=cnt[x][1]; cnt[x][1]+=val;cnt[pos[x]][2]+=val; if ((cnt[x][1]==0) && (base==1)) {cnt[x][3]--;cnt[pos[x]][4]--;} if ((cnt[x][1]==1) && (base==0)) {cnt[x][3]++;cnt[pos[x]][4]++;} } void ask(int l,int r,int x) { int ret1=0,ret2=0; if (pos[l]==pos[r]) { for (int i=l;i<=r;i++) ret1+=cnt[i][1],ret2+=cnt[i][3]; } else { for (int i=l;i<=st[pos[l]];i++) ret1+=cnt[i][1],ret2+=cnt[i][3]; for (int i=st[pos[r]-1]+1;i<=r;i++) ret1+=cnt[i][1],ret2+=cnt[i][3]; for (int i=pos[l]+1;i<=pos[r]-1;i++) ret1+=cnt[i][2],ret2+=cnt[i][4]; } ans[q[x].id][1]=ret1;ans[q[x].id][2]=ret2; } int main() { n=read();m=read(); for (int i=1;i<=n;i++) a[i]=read(); 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; } build();sort(q+1,q+m+1,cmp); int l=1,r=0; for (int i=1;i<=m;i++) { for (;r<q[i].r;r++) modify(a[r+1],1); for (;r>q[i].r;r--) modify(a[r],-1); for (;l<q[i].l;l++) modify(a[l],-1); for (;l>q[i].l;l--) modify(a[l-1],1); ask(q[i].a,q[i].b,i); } for (int i=1;i<=m;i++) printf("%d %d\n",ans[i][1],ans[i][2]); return 0; }