BZOJ_3809_Gty的二逼妹子序列 && BZOJ_3236_[Ahoi2013]作业 _莫队+分块
BZOJ_3809_Gty的二逼妹子序列 && BZOJ_3236_[Ahoi2013]作业 _莫队+分块
Description
Autumn和Bakser又在研究Gty的妹子序列了!但他们遇到了一个难题。 对于一段妹子们,他们想让你帮忙求出这之内美丽度∈[a,b]的妹子的美丽度的种类数。 为了方便,我们规定妹子们的美丽度全都在[1,n]中。 给定一个长度为n(1<=n<=100000)的正整数序列s(1<=si<=n),对于m(1<=m<=1000000)次询问“l,r,a,b”,每次输出sl...sr中,权值∈[a,b]的权值的种类数。Input
第一行包括两个整数n,m(1<=n<=100000,1<=m<=1000000),表示数列s中的元素数和询问数。 第二行包括n个整数s1...sn(1<=si<=n)。 接下来m行,每行包括4个整数l,r,a,b(1<=l<=r<=n,1<=a<=b<=n),意义见题目描述。 保证涉及的所有数在C++的int内。 保证输入合法。Output
对每个询问,单独输出一行,表示sl...sr中权值∈[a,b]的权值的种类数。
Sample Input
10 104 4 5 1 4 1 5 1 2 1
5 9 1 2
3 4 7 9
4 4 2 5
2 3 4 7
5 10 4 4
3 9 1 1
1 4 5 9
8 9 3 3
2 2 1 6
8 9 1 4
Sample Output
20
0
2
1
1
1
0
1
2
HINT
样例的部分解释: 5 9 1 2 子序列为4 1 5 1 2 在[1,2]里的权值有1,1,2,有2种,因此答案为2。 3 4 7 9 子序列为5 1 在[7,9]里的权值有5,有1种,因此答案为1。 4 4 2 5 子序列为1 没有权值在[2,5]中的,因此答案为0。 2 3 4 7 子序列为4 5 权值在[4,7]中的有4,5,因此答案为2。 建议使用输入/输出优化。 分析: 经典的莫队练习题。 可以用树状数组修改,但因为修改和查询复杂度都是$O(logn)$,修改次数为$O(n\sqrt m)$,查询次数$O(m)$,总时间复杂度$O(n\sqrt m logn)$。 如果把值域分块的话修改的复杂度$O(1)$,查询复杂度$O(\sqrt n)$,总时间复杂度$O(n\sqrt m)$。 把询问像莫队那么搞,然后把值域分块,每个块维护块内答案,找答案时在$a\thicksim b$ 的块里面找答案。 代码(3809):#include <stdio.h> #include <string.h> #include <algorithm> #include <math.h> using namespace std; char nc() { static char buf[100000],*p1,*p2; return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; } inline int rd() { register int x=0; register char s=nc(); while(s<'0'||s>'9')s=nc(); while(s>='0'&&s<='9')x=(x<<3)+(x<<1)+s-'0',s=nc(); return x; } #define N 100001 int n,m,c ,pos ,L[1050],R[1050],size,block,ansblo[1050],h ,ans[N*10]; struct A { int l,r,a,b,id; }q[N*10]; bool cmp(const A &x,const A &y) { if(pos[x.l]!=pos[y.l]) return x.l<y.l; return x.r<y.r; } int query(int l,int r) { int p=pos[l],q=pos[r],ans=0,i; if(p==q) { for(i=l;i<=r;i++) { if(h[i]) ans++; } return ans; } for(i=p+1;i<q;i++) { ans+=ansblo[i]; } for(i=l;i<=R[p]代码(3263):;i++) { if(h[i]) ans++; } for(i=L[q];i<=r;i++) { if(h[i]) ans++; } return ans; } void del(int x) { h[x]--; if(h[x]==0) ansblo[pos[x]]--; } void add(int x) { h[x]++; if(h[x]==1) ansblo[pos[x]]++; } void solve() { int l=1,r=0,i; for(i=1;i<=m;i++) { while(l<q[i].l) del(c[l]),l++; while(r>q[i].r) del(c[r]),r--; while(l>q[i].l) l--,add(c[l]); while(r<q[i].r) r++,add(c[r]); ans[q[i].id]=query(q[i].a,q[i].b); } } int main() { n=rd(); m=rd(); int i,j,size=sqrt(n); block=n/size; for(i=1;i<=block;i++) { L[i]=R[i-1]+1; R[i]=size*i; for(j=L[i];j<=R[i];j++) { c[j]=rd(); pos[j]=i; } } if(R[block]!=n) { block++; L[block]=R[block-1]+1; R[block]=n; for(i=L[block];i<=n;i++) { c[i]=rd(); pos[i]=block; } } for(i=1;i<=m;i++) { q[i].l=rd(); q[i].r=rd(); q[i].a=rd(); q[i].b=rd(); q[i].id=i; } sort(q+1,q+m+1,cmp); solve(); for(i=1;i<=m;i++) { printf("%d\n",ans[i]); } }
#include <stdio.h> #include <string.h> #include <algorithm> #include <math.h> using namespace std; char nc() { static char buf[100000],*p1,*p2; return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; } inline int rd() { register int x=0; register char s=nc(); while(s<'0'||s>'9')s=nc(); while(s>='0'&&s<='9')x=(x<<3)+(x<<1)+s-'0',s=nc(); return x; } #define N 100001 int n,m,c ,pos ,L[1050],R[1050],size,block,ansblo[1050],h ,ans[N*10],ans1[N*10],ansblo1[1050]; struct A { int l,r,a,b,id; }q[N*10]; bool cmp(const A &x,const A &y) { if(pos[x.l]!=pos[y.l]) return x.l<y.l; return x.r<y.r; } int query(int l,int r) { int p=pos[l],q=pos[r],ans=0,i; if(p==q) { for(i=l;i<=r;i++) { if(h[i]) ans++; } return ans; } for(i=p+1;i<q;i++) { ans+=ansblo[i]; } for(i=l;i<=R[p];i++) { if(h[i]) ans++; } for(i=L[q];i<=r;i++) { if(h[i]) ans++; } return ans; } int query1(int l,int r) { int p=pos[l],q=pos[r],i,ans=0; if(p==q) { for(i=l;i<=r;i++) { if(h[i]) ans+=h[i]; } return ans; } for(i=p+1;i<q;i++) ans+=ansblo1[i]; for(i=l;i<=R[p];i++) if(h[i]) ans+=h[i]; for(i=L[q];i<=r;i++) if(h[i]) ans+=h[i]; return ans; } void del(int x) { h[x]--; if(h[x]==0) ansblo[pos[x]]--; ansblo1[pos[x]]--; } void add(int x) { h[x]++; if(h[x]==1) ansblo[pos[x]]++; ansblo1[pos[x]]++; } void solve() { int l=1,r=0,i; for(i=1;i<=m;i++) { while(l<q[i].l) del(c[l]),l++; while(r>q[i].r) del(c[r]),r--; while(l>q[i].l) l--,add(c[l]); while(r<q[i].r) r++,add(c[r]); ans[q[i].id]=query(q[i].a,q[i].b); ans1[q[i].id]=query1(q[i].a,q[i].b); } } int main() { n=rd(); m=rd(); int i,j,size=sqrt(n); block=n/size; for(i=1;i<=block;i++) { L[i]=R[i-1]+1; R[i]=size*i; for(j=L[i];j<=R[i];j++) { c[j]=rd(); pos[j]=i; } } if(R[block]!=n) { block++; L[block]=R[block-1]+1; R[block]=n; for(i=L[block];i<=n;i++) { c[i]=rd(); pos[i]=block; } } for(i=1;i<=m;i++) { q[i].l=rd(); q[i].r=rd(); q[i].a=rd(); q[i].b=rd(); q[i].id=i; } sort(q+1,q+m+1,cmp); solve(); for(i=1;i<=m;i++) { printf("%d %d\n",ans1[i],ans[i]); } }
- BZOJ 3809: Gty的二逼妹子序列 & 3236: [Ahoi2013]作业 [莫队]
- 【BZOJ3809/3236】Gty的二逼妹子序列 [Ahoi2013]作业 莫队算法+分块
- [BZOJ 3236] [Ahoi2013] 作业 && [BZOJ 3809] 【莫队(+分块)】
- [BZOJ3809]Gty的二逼妹子序列(莫队+分块)
- Bzoj 3809: Gty的二逼妹子序列 莫队,分块
- BZOJ 3809: Gty的二逼妹子序列(莫队+分块)
- 【BZOJ3809】Gty的二逼妹子序列 (莫队+分块)
- [bzoj3809]Gty的二逼妹子序列_莫队_分块
- 【BZOJ 3809】 3809: Gty的二逼妹子序列 (莫队+分块)
- BZOJ 3809 Gty的二逼妹子序列 莫队算法+分块
- 【BZOJ-3809】Gty的二逼妹子序列 分块 + 莫队算法
- 【BZOJ3809】Gty的二逼妹子序列 莫队 分块
- 【BZOJ 3809】Gty的二逼妹子序列 莫队+分块
- 【BZOJ3809】Gty的二逼妹子序列【莫队算法】【分块】
- 【莫队算法】【权值分块】bzoj3809 Gty的二逼妹子序列
- 【bzoj3809】【GTY的二逼妹子序列】【莫队+分块】
- BZOJ 3809 Gty的二逼妹子序列(莫队+分块)
- 【bzoj3809】Gty的二逼妹子序列 莫队+分块
- BZOJ 3809 Gty的二逼妹子序列 | 莫队 + 分块
- [BZOJ3809]Gty的二逼妹子序列(莫队+分块)