[bzoj3809]Gty的二逼妹子序列/[bzoj3236][Ahoi2013]作业

[bzoj3809]Gty的二逼妹子序列/[bzoj3236][Ahoi2013]作业

bzoj   bzoj

题目大意:一个序列,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 }
View Code
posted @ 2019-07-26 18:55  RikukiIX  阅读(202)  评论(0编辑  收藏  举报