COGS.1822.[AHOI2013]作业(莫队 树状数组/分块)
2018-02-09 13:30
253 查看
题目链接: COGS、BZOJ3236
Upd: 树状数组实现的是单点加 区间求和,采用值域分块可以\(O(1)\)修改\(O(sqrt(n))\)查询。同BZOJ3809.
莫队为\(O(n^{1.5})\)次修改和\(O(n)\)次查询。
注意这两个需求并不平衡,所以在搭配数据结构时常使用分块而不是线段树。
(转自莫队复杂度分析 Meiku Kazami)
分块在bzoj上还要20s,rank1(wys)的5s怎么跑的--。
1.莫队+树状数组
2.莫队+值域分块
Upd: 树状数组实现的是单点加 区间求和,采用值域分块可以\(O(1)\)修改\(O(sqrt(n))\)查询。同BZOJ3809.
莫队为\(O(n^{1.5})\)次修改和\(O(n)\)次查询。
注意这两个需求并不平衡,所以在搭配数据结构时常使用分块而不是线段树。
(转自莫队复杂度分析 Meiku Kazami)
分块在bzoj上还要20s,rank1(wys)的5s怎么跑的--。
1.莫队+树状数组
/* 每个[l,r]的询问中又多了[a,b]值的限制。原先now是所有种类的个数,所以用 莫队+树状数组做 两问,维护两个树状数组 O(m*sqrt(n)*logn) */ #include<cmath> #include<cstdio> #include<cctype> #include<algorithm> using namespace std; const int N=1e5+5,M=1e6+5; int n,m,size,A ,t1 ,t2 ,times ,Ans1[M],Ans2[M]; struct Ques { int l,r,a,b,id; bool operator <(const Ques &x)const { return l/size==x.l/size ? r<x.r : l/size<x.l/size; } }q[M]; inline int read() { int now=0,f=1;register char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);now=now*10+c-'0',c=getchar()); return now*f; } inline int lb(int x) { return x&-x; } void Update(int p,int v,int *t) { while(p<=n) t[p]+=v, p+=lb(p); } int Query(int p,int *t) { int res=0; while(p) res+=t[p], p-=lb(p); return res; } void Add(int p) { Update(A[p],1,t1); if(!times[A[p]]) Update(A[p],1,t2); ++times[A[p]]; } void Subd(int p) { Update(A[p],-1,t1); --times[A[p]]; if(!times[A[p]]) Update(A[p],-1,t2); } int main() { freopen("ahoi2013_homework.in","r",stdin); freopen("ahoi2013_homework.out","w",stdout); n=read(),m=read(); size=sqrt(n); 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].a=read(), q[i].b=read(), q[i].id=i; sort(q+1,q+1+m); for(int l=1,r=0,i=1;i<=m;++i) { int ln=q[i].l,rn=q[i].r; while(l<ln) Subd(l++); while(l>ln) Add(--l); while(r<rn) Add(++r); while(r>rn) Subd(r--); Ans1[q[i].id]=Query(q[i].b,t1)-Query(q[i].a-1,t1),//注意值的区间是[a,b]不是[l,r] Ans2[q[i].id]=Query(q[i].b,t2)-Query(q[i].a-1,t2); // printf("%d:%d %d ans1:%d ans2:%d\n",q[i].id,ln,rn,Ans1[q[i].id],Ans2[q[i].id]); } for(int i=1;i<=m;++i) printf("%d %d\n",Ans1[i],Ans2[i]); fclose(stdin);fclose(stdout); return 0; }
2.莫队+值域分块
#include <cmath> #include <cstdio> #include <cctype> #include <algorithm> #define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++) const int N=1e5+5,MAXIN=2e6; int n,m,size,Ans1[N*10],Ans2[N*10],A ,tm ,bel ,sum1[500],sum2[500]; char IN[MAXIN],*SS=IN,*TT=IN; struct Ask { int l,r,a,b,id; bool operator <(const Ask &a)const { return l/size==a.l/size ? r<a.r : l/size<a.l/size;//更快 WTF // return l/size==a.l/size?((l-1)/size&1 ? r>a.r : r<a.r):l/size<a.l/size; } }q[N*10]; inline int read() { int now=0;register char c=gc(); for(;!isdigit(c);c=gc()); for(;isdigit(c);now=now*10+c-'0',c=gc()); return now; } int Query(int *s,int l,int r,bool f) { int res=0,tmp=std::min(r,bel[l]*size); for(int i=l; i<=tmp; ++i) res+= f?(tm[i]>0):tm[i]; if(bel[l]!=bel[r]) for(int i=(bel[r]-1)*size+1; i<=r; ++i) res+= f?(tm[i]>0):tm[i]; for(int i=bel[l]+1; i<bel[r]; ++i) res+=s[i]; return res; } void Add(int p) { if(++tm[p]==1) ++sum2[bel[p]]; ++sum1[bel[p]]; } void Subd(int p) { if(!--tm[p]) --sum2[bel[p]]; --sum1[bel[p]]; } int main() { n=read(), m=read(), size=sqrt(n);;//size=n/sqrt(m*2/3) //也没有更快 数组大小还要注意 for(int i=1; i<=n; ++i) bel[i]=(i-1)/size+1, A[i]=read(); for(int i=1; i<=m; ++i) q[i].l=read(),q[i].r=read(),q[i].a=read(),q[i].b=read(),q[i].id=i; std::sort(q+1,q+1+m); for(int l=1,r=0,ln,rn,i=1; i<=m; ++i) { int ln=q[i].l,rn=q[i].r; while(l<ln) Subd(A[l++]); while(l>ln) Add(A[--l]); while(r<rn) Add(A[++r]); while(r>rn) Subd(A[r--]); Ans1[q[i].id]=Query(sum1,q[i].a,q[i].b,0), Ans2[q[i].id]=Query(sum2,q[i].a,q[i].b,1); } for(int i=1; i<=m; ++i) printf("%d %d\n",Ans1[i],Ans2[i]); return 0; }
相关文章推荐
- 莫队+分块+树状数组 【Ahoi2013】 作业 bzoj3236
- BZOJ3236 [Ahoi2013]作业 【莫队 + 树状数组】
- 【莫队算法】【权值分块】bzoj3236 [Ahoi2013]作业
- [BZOJ3236][Ahoi2013]作业(莫队+分块)
- Bzoj 3236: [Ahoi2013]作业 莫队,分块
- bzoj 3236: [Ahoi2013]作业 莫队算法+分块
- 【BZOJ3809/3236】Gty的二逼妹子序列 [Ahoi2013]作业 莫队算法+分块
- BZOJ_3809_Gty的二逼妹子序列 && BZOJ_3236_[Ahoi2013]作业 _莫队+分块
- BZOJ3236: [Ahoi2013]作业 莫队+分块
- bzoj 3236: [Ahoi2013]作业 (莫队+分块)
- [BZOJ 3236] [Ahoi2013] 作业 && [BZOJ 3809] 【莫队(+分块)】
- COGS:1822. [AHOI2013]作业
- [ 莫队 树状数组 ] [ AHOI2013 ] BZOJ3236
- [BZOJ3236][Ahoi2013]作业(莫队+树状数组)
- 【BZOJ3289】【莫队分块+树状数组求逆序对】Mato的文件管理
- BZOJ3236 作业 [莫队算法][树状数组]
- BZOJ 3236: [Ahoi2013]作业( 莫队 + BIT )
- BZOJ 3236: [Ahoi2013]作业|莫队算法|树状数组
- 【BZOJ】【P3236】【Ahoi2013】【作业】【题解】【莫队】
- Bzoj 3289: Mato的文件管理 莫队,树状数组,逆序对,离散化,分块