思路
因为每次a和b不相同
用莫队+分块或者莫队+树状数组即可维护
不过分块单点修改是O(1)的,更优
我用树状数组维护了一下,只能开O2通过
代码
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
struct BIT{
int tr[10000000],MAXW;
int lowbit(int x){
return x&(-x);
}
void add(int pos,int c){
pos++;
while(pos<=MAXW){
tr[pos]+=c;
pos+=lowbit(pos);
}
}
int query(int pos){
pos++;
int ans=0;
while(pos){
ans+=tr[pos];
pos-=lowbit(pos);
}
return ans;
}
}times,nums;
int color[10000000],a[100100],n,m,L,R,sz,num,belong[100100],ans1[100100],ans2[100100];
struct Query{
int l,r,a,b,id;
bool operator < (const Query &b) const{
return (belong[l]==belong[b.l])?r<b.r:belong[l]<belong[b.l];
}
}Q[100100];
void init(void){
sz=sqrt(n);
num=n/sz;
if(n%sz)
num++;
for(int i=1;i<=n;i++)
belong[i]=i/sz+1;
}
void moveL(int opt){
if(opt==1){
times.add(a[L],-1);
if(color[a[L]]==1)
nums.add(a[L],-1);
color[a[L]]--;
L++;
}
else{
L--;
times.add(a[L],1);
if(color[a[L]]==0)
nums.add(a[L],1);
color[a[L]]++;
}
}
void moveR(int opt){
if(opt==1){
R++;
times.add(a[R],1);
if(color[a[R]]==0)
nums.add(a[R],1);
color[a[R]]++;
}
else{
times.add(a[R],-1);
if(color[a[R]]==1)
nums.add(a[R],-1);
color[a[R]]--;
R--;
}
}
int main(){
scanf("%d %d",&n,&m);
init();
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
times.MAXW=nums.MAXW=max(nums.MAXW,a[i]+10);
}
for(int i=1;i<=m;i++)
scanf("%d %d %d %d",&Q[i].l,&Q[i].r,&Q[i].a,&Q[i].b),Q[i].id=i;
sort(Q+1,Q+m+1);
L=R=0;
for(int i=1;i<=m;i++){
while(L<Q[i].l)
moveL(1);
while(L>Q[i].l)
moveL(-1);
while(R<Q[i].r)
moveR(1);
while(R>Q[i].r)
moveR(-1);
ans1[Q[i].id]=times.query(Q[i].b)-times.query(Q[i].a-1);
ans2[Q[i].id]=nums.query(Q[i].b)-nums.query(Q[i].a-1);
}
for(int i=1;i<=m;i++)
printf("%d %d\n",ans1[i],ans2[i]);
return 0;
}