莫队+分块+树状数组 【Ahoi2013】 作业 bzoj3236
2017-01-12 09:08
253 查看
题目大意:
给定一个长度为n的序列,m个询问,询问一段区间内大于等于a小于等于b的数的个数和数值的个数。
n=1e5,m=1e6
题目分析:
看到大于等于a小于等于b这个条件,我们可以想到用树状数组来维护区间内比每个数字小的数的个数(数值同理,判断一下就好惹),每次修改都是logn的,并且可以发现,在原有的序列中新加入或减去一个数字,只需要一次修改,也就符合了莫队算法需要的知道[l,r]的答案,就能快速得到[l+1,r],[l-1,r],[l,r+1],[l,r-1]的答案的性质。但是询问数仍然很大,所以我们考虑分块,把时间复杂度降一个根号,就过了。
时间复杂度O(msqrt(n)logn)
不过我写的莫队真是很辣鸡啊,华丽丽地卡了评测……
![](http://img.blog.csdn.net/20170112090256935?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvVG9kb2Jl/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
代码如下:
给定一个长度为n的序列,m个询问,询问一段区间内大于等于a小于等于b的数的个数和数值的个数。
n=1e5,m=1e6
题目分析:
看到大于等于a小于等于b这个条件,我们可以想到用树状数组来维护区间内比每个数字小的数的个数(数值同理,判断一下就好惹),每次修改都是logn的,并且可以发现,在原有的序列中新加入或减去一个数字,只需要一次修改,也就符合了莫队算法需要的知道[l,r]的答案,就能快速得到[l+1,r],[l-1,r],[l,r+1],[l,r-1]的答案的性质。但是询问数仍然很大,所以我们考虑分块,把时间复杂度降一个根号,就过了。
时间复杂度O(msqrt(n)logn)
不过我写的莫队真是很辣鸡啊,华丽丽地卡了评测……
代码如下:
#include<cstdio> #include<algorithm> #include<cmath> #define N 120000 #define M 1200000 using namespace std; struct query{ int l,r,a,b,num; bool operator < (const query&) const; }q[M]; int n,m,blocks; int a ,belong ; int c ,d ,cnt ; int ans1[M],ans2[M]; int lowbit(int c) {return c&-c;} bool query :: operator < (const query &c) const{ return belong[l]<belong[c.l] || (belong[l]==belong[c.l] && r<c.r); } void update(int x,int y) { cnt[x]+=y; for(int t=x;t<=n;t+=lowbit(t)) c[t]+=y; if((y==1 && cnt[x]==1) || (y==-1 && cnt[x]==0) ) for(int t=x;t<=n;t+=lowbit(t)) d[t]+=y; return; } void query(int a,int b,int &ans1,int &ans2) { for(;b;b-=lowbit(b)) ans1+=c[b],ans2+=d[b]; for(a=a-1;a;a-=lowbit(a)) ans1-=c[a],ans2-=d[a]; return; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&a[i]); 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].num=i; blocks=(int)ceil(sqrt(n)); for(int i=1;i<=n;i++) belong[i]=(i-1)/blocks+1; sort(q+1,q+1+m); int l=1,r=0; for(int i=1;i<=m;i++) { while(r<q[i].r) update(a[++r], 1); while(r>q[i].r) update(a[r--],-1); while(l<q[i].l) update(a[l++],-1); while(l>q[i].l) update(a[--l], 1); query(q[i].a,q[i].b,ans1[q[i].num],ans2[q[i].num]); } for(int i=1;i<=m;i++) printf("%d %d\n",ans1[i],ans2[i]); return 0; }
相关文章推荐
- COGS.1822.[AHOI2013]作业(莫队 树状数组/分块)
- BZOJ3236 [Ahoi2013]作业 【莫队 + 树状数组】
- Bzoj 3236: [Ahoi2013]作业 莫队,分块
- [BZOJ 3236] [Ahoi2013] 作业 && [BZOJ 3809] 【莫队(+分块)】
- BZOJ3236: [Ahoi2013]作业 树状数组维护 莫队
- [ 莫队 树状数组 ] [ AHOI2013 ] BZOJ3236
- BZOJ_3809_Gty的二逼妹子序列 && BZOJ_3236_[Ahoi2013]作业 _莫队+分块
- bzoj 3236: [Ahoi2013]作业 (莫队+分块)
- 【莫队算法】【权值分块】bzoj3236 [Ahoi2013]作业
- bzoj 3236: [Ahoi2013]作业 莫队算法+分块
- BZOJ3236: [Ahoi2013]作业 莫队+分块
- BZOJ3236 作业 [莫队算法][树状数组]
- Bzoj3236:[Ahoi2013]作业:莫队算法+树状数组
- [BZOJ3236][Ahoi2013]作业(莫队+分块)
- 【BZOJ3809/3236】Gty的二逼妹子序列 [Ahoi2013]作业 莫队算法+分块
- 【BZOJ3289】【莫队分块+树状数组求逆序对】Mato的文件管理
- BZOJ3236 [Ahoi2013]作业
- [bzoj3236][Ahoi2013]作业(莫队+树状数组)
- BZOJ3236:[AHOI2013]作业——题解
- BZOJ3236: [Ahoi2013]作业