题目:
题目链接:Gty的二逼妹子序列
题解:
什么**题目嘛,一点都没有意思,因为个数组大小卡了我将近四天,我查了好长时间才查出来,快气死了,,,(╯>д<)╯⁽˙³˙⁾
(下面才是正经的题解:)
题目中是让求l,r中的权值在(a,b)中的个数,所以就会想到用莫队进行对了l,r进行处理,然后在按套路开个桶,在对于(a,b)(就是对所有权值)进行分块写,(这里其实可以用离散化的,但是这个范围就不需要了吧),这样的就复杂度就降低了很多。
其中最重要的就是对于权值的分块。
(重要的还是数组大小啊,,,(坑死我了))
代码:
#include<bits/stdc++.h>
using namespace std;
inline int read()
{
int s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch<='9'&&ch>='0')s=s*10+ch-'0',ch=getchar();
return s*w;
}
const int sea=1000005;
const int pool=1005;
struct hit{int l,r,id,x,y;}q[sea];
int n,m,block,num,belong[sea],a[sea],ans[sea],l[pool],r[pool],lazy[pool],f[sea];
bool cmp(hit a,hit b){if(belong[a.l]==belong[b.l]) return a.r<b.r;return a.l<b.l;}
int fk(int x,int y)//权值分块
{
int tmp=0;
for(int i=belong[x]+1;i<belong[y];i++) tmp+=lazy[i];
if(belong[x]==belong[y])
for(int i=x;i<=y;i++) {if(f[i]) tmp++;}
else
{
for(int i=x;i<=r[belong[x]];i++) if(f[i]) tmp++;
for(int i=l[belong[y]];i<=y;i++) if(f[i]) tmp++;
}
return tmp;
}
void add(int x){f[x]++; if(f[x]==1) lazy[belong[x]]++;}
void del(int x){f[x]--; if(f[x]==0) lazy[belong[x]]--;}
int main()
{
n=read(); m=read(); block=sqrt(n/2);
for(int i=1;i<=n;i++) belong[i]=(i-1)/block+1;
num=n/block; if(num%block) num++;
for(int i=1;i<=num;i++) r[i]=i*block,l[i]=(i-1)*block+1;
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].x=read(),q[i].y=read(),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) del(a[L]),L++;
while(L>q[i].l) L--,add(a[L]);
while(R<q[i].r) R++,add(a[R]);
while(R>q[i].r) del(a[R]),R--;
ans[q[i].id]=fk(q[i].x,q[i].y);
}
for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
return 0;
}