这道题没什么可说的吧。和上一题思路完全一样,不过开数组的时候谨慎一些,毕竟只有28MB。
一定不要直接肝分块!!!这种复杂度只能上莫队加权值分块。
#include<bits/stdc++.h> using namespace std; const int N=1e5+10; const int M=1e6+10; struct node{int l,r,L,R,id,ans;}q[M]; int n,m,s,t,a[N],vis[N],sum[N]; bool cmp(node a,node b){return (a.l-1)/s+1==(b.l-1)/s+1?a.r<b.r:a.l<b.l;} bool CMP(node a,node b){return a.id<b.id;} void update(int x,int val){ if(vis[x]==0&&val==1) sum[(x-1)/s+1]++; else if(vis[x]==1&&val==-1) sum[(x-1)/s+1]--; vis[x]+=val; } int query(int l,int r){ int p=l/s,q=r/s; if(l%s==1) p++; else if(l%s) p+=2; else p++; int res=0; if(q-p<0){ for(int i=l;i<=r;++i) res+=(vis[i]>0); return res; }else{ for(int i=l;i<=(p-1)*s;++i) res+=(vis[i]>0); for(int i=p;i<=q;++i) res+=sum[i]; for(int i=q*s+1;i<=r;++i) res+=(vis[i]>0); return res; } } int main(){ scanf("%d%d",&n,&m); s=sqrt(1.0*n*n/m);t=n/s; for(int i=1;i<=n;++i) scanf("%d",&a[i]); for(int i=1;i<=m;++i) scanf("%d%d%d%d",&q[i].l,&q[i].r,&q[i].L,&q[i].R),q[i].id=i; sort(q+1,q+m+1,cmp); int l=1,r=0; for(int i=1;i<=m;++i){ while(l<q[i].l) update(a[l++],-1); while(l>q[i].l) update(a[--l],1); while(r<q[i].r) update(a[++r],1); while(r>q[i].r) update(a[r--],-1); q[i].ans=query(q[i].L,q[i].R); } sort(q+1,q+m+1,CMP); for(int i=1;i<=m;++i) printf("%d\n",q[i].ans); return 0; }