分块随笔入门T2
Posted dancer16
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分块随笔入门T2相关的知识,希望对你有一定的参考价值。
小M的简单题时间限制: 1 Sec 内存限制: 128 MB 提交: - 解决: - [提交][讨论版]
题目描述
小M是某知名高中的学生,有一天,他请他的n个同学吃苹果,同学们排成一行,且手中已经有一些苹果。为了表示他的大方,有时他会给l到r的同学x个苹果,但为了了解分配的情况,有时他会询问l到r的同学中拥有的苹果数小于x的人的个数。现在,小M想让你帮他解决这道简单题。
输入
第一行:两个整数n,m表示n个同学,m组询问。
第二行:n个数,a[1],a[2]...a[n],a[i]表示第i个同学一开始手中的苹果数。(0<=a[i]<=3e4)
第3~m+2行:每行表示一组询问,格式为C l r x表示给l到r的同学x个苹果,或者Q l r x表示询问l到r的同学中拥有的苹果数小于x的人的个数。(1<=l<=r<=n,0<=x<=3e4)
输出格式:
每行一个数,输出l到r的同学中拥有的苹果数小于x的人的个数。
输出
每行一个数,输出l到r的同学中拥有的苹果数小于x的人的个数。
样例输入
5 5 1 6 3 2 3 Q 1 3 3 C 1 2 2 Q 3 4 3 C 2 3 1 Q 2 3 4
5 4 2 3 1 3 4 C 4 5 3 C 1 5 1 C 2 3 2 Q 1 3 4
5 4 2 3 1 3 4 C 4 5 3 C 1 5 1 C 2 3 2 Q 1 3 4
样例输出
1 1 0
1
1
分块模版题
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<vector> #include<cmath> using namespace std; vector<int>vec[1004]; int n,blo,v[30005],m,bl[30005],lazy[1004]; void reset(int x) { vec[x].clear(); for(int i=(x-1)*blo+1;i<=min(x*blo,n);i++) vec[x].push_back(v[i]); sort(vec[x].begin(),vec[x].end()); } void change(int l,int r,int val) { for(int i=l;i<=min(blo*bl[l],r);i++) { v[i]+=val; } reset(bl[l]); if(bl[l]!=bl[r]) { for(int i=(bl[r]-1)*blo+1;i<=r;i++) v[i]+=val; reset(bl[r]); } for(int i=bl[l]+1;i<=bl[r]-1;i++) lazy[i]+=val; } int query(int l,int r,int val) { int ans=0; for(int i=l;i<=min(r,bl[l]*blo);i++) if(v[i]+lazy[bl[l]]<val)ans++; if(bl[l]!=bl[r]) { for(int i=blo*(bl[r]-1)+1;i<=r;i++) if(v[i]+lazy[bl[r]]<val) ans++; } for(int i=bl[l]+1;i<=bl[r]-1;i++) ans+=lower_bound(vec[i].begin(),vec[i].end(),val-lazy[i])-vec[i].begin(); return ans; } int main() { scanf("%d %d",&n,&m); blo=sqrt(n); for(int i=1;i<=n;i++) { scanf("%d",&v[i]); bl[i]=(i-1)/blo+1; vec[bl[i]].push_back(v[i]); } for(int i=1;i<=bl[n];i++) sort(vec[i].begin(),vec[i].end()); char char_[2]; for(int i=1;i<=m;i++) { int x,y,z; scanf("%s %d %d %d",char_,&x,&y,&z); if(char_[0]==‘C‘) { change(x,y,z); }else { printf("%d\n",query(x,y,z)); } } }
以上是关于分块随笔入门T2的主要内容,如果未能解决你的问题,请参考以下文章