[bzoj3809]Gty的二逼妹子序列/[bzoj3236][Ahoi2013]作业
[bzoj3809]Gty的二逼妹子序列/[bzoj3236][Ahoi2013]作业
题目大意:一个序列,m个询问在$[l,r]$区间的$[x,y]$范围内的数的个数/种类。
思路:
因为看不出来怎么做,所以考虑莫队。
太懒想写个树状数组但是$n\sqrt{n}log_{n}$太虚
所以将数分块,修改$O(1)$,查询$O(\sqrt{n})$
完结
1 #include<algorithm> 2 #include<cstdio> 3 #include<cmath> 4 using namespace std; 5 const int N=114514,SN=366; 6 template<typename tp>inline void read(tp &kk){ 7 tp ret=0,f=1;char ch=getchar(); 8 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 9 while(ch>='0'&&ch<='9'){ret=ret*10+ch-'0';ch=getchar();} 10 kk=ret*f; 11 } 12 int n,m,a[N],bl[N],bs; 13 struct ques 14 { 15 int l,r,x,y,id; 16 bool operator < (const ques &a)const{return bl[l]==bl[a.l]?r<a.r:bl[l]<bl[a.l];} 17 void init(int i){id=i;read(l),read(r),read(x),read(y);} 18 }q[N]; 19 20 struct ans 21 { 22 int a1,a2; 23 ans(){a1=a2=0;} 24 }prt[N]; 25 26 struct ShangYang 27 { 28 int l[SN],r[SN],buk[SN],bukk[SN],b[N],po[N],sz; 29 void start() 30 { 31 sz=ceil(sqrt(100000)); 32 int bb=0; 33 for(int i=1;i<=n;i+=sz) 34 { 35 bb++; 36 l[bb]=i; 37 r[bb]=min(i+sz-1,n); 38 for(int j=l[bb];j<=r[bb];j++) b[j]=bb; 39 } 40 } 41 void add(int x) 42 { 43 if(!po[x]) bukk[b[x]]++; 44 po[x]++; 45 buk[b[x]]++; 46 } 47 void mus(int x) 48 { 49 po[x]--; 50 buk[b[x]]--; 51 if(!po[x]) bukk[b[x]]--; 52 } 53 ans query(int x,int y) 54 { 55 ans ret; 56 int bx=b[x],by=b[y]; 57 if(bx==by) 58 { 59 for(int i=x;i<=y;i++) 60 ret.a1+=po[i],ret.a2+=(!!po[i]); 61 }else 62 { 63 for(int i=bx+1;i<by;i++) 64 ret.a1+=buk[i],ret.a2+=bukk[i]; 65 for(int i=x;i<=r[bx];i++) 66 ret.a1+=po[i],ret.a2+=(!!po[i]); 67 for(int i=l[by];i<=y;i++) 68 ret.a1+=po[i],ret.a2+=(!!po[i]); 69 } 70 return ret; 71 } 72 }sy; 73 74 void icu() 75 { 76 int l=1,r=0; 77 for(int i=1;i<=m;i++) 78 { 79 while(r<q[i].r) sy.add(a[++r]); 80 while(l>q[i].l) sy.add(a[--l]); 81 while(r>q[i].r) sy.mus(a[r--]); 82 while(l<q[i].l) sy.mus(a[l++]); 83 prt[q[i].id]=sy.query(q[i].x,q[i].y); 84 } 85 } 86 87 int main() 88 { 89 read(n),read(m); 90 bs=ceil(sqrt(n)); 91 for(int i=1;i<=n;i++) read(a[i]),bl[i]=(i-1)/bs+1; 92 for(int i=1;i<=m;i++) q[i].init(i); 93 // puts("114514"); 94 sy.start(); 95 sort(q+1,q+1+m); 96 icu(); 97 // puts("1919810"); 98 for(int i=1;i<=m;i++) printf("%d %d\n",prt[i].a1,prt[i].a2); 99 return 0; 100 }