小M的简单题(easy)
时间限制:3s 内存限制:128MB
【题目描述】
小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的人的个数。
【样例输入1】
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
【样例输出1】
1
1
0
【样例输入2】
5 4
2 3 1 3 4
C 4 5 3
C 1 5 1
C 2 3 2
Q 1 3 4
【样例输出2】
1
【数据范围】
N M
第1~3组 1000 1000
第4~5组 30000 1000
第6~10组 30000 30000
#include<cstdio> #include<iostream> #include<cmath> #include<vector> #include<algorithm> using namespace std; vector<int> ve[200]; int n,m,block,bl[100005],tag[100005],a[100005]; void reset(int x) { ve[x].clear(); for (int i=block*(x-1)+1; i<=min(block*x,n);i++) ve[x].push_back(a[i]); sort(ve[x].begin(),ve[x].end()); } void change(int l,int r,int x) { for (int i=l; i<=min(bl[l]*block,r);i++) a[i]+=x; reset(bl[l]); if (bl[l]!=bl[r]) for (int i=block*(bl[r]-1)+1; i<=r; i++) a[i]+=x; reset(bl[r]); for (int i=bl[l]+1; i<=bl[r]-1; i++) tag[i]+=x; } int query(int l,int r,int x) { int ans=0; for (int i=l; i<=min(bl[l]*block,r);i++) if (a[i]+tag[bl[i]]<x) ans++; if (bl[l]!=bl[r]) for (int i=block*(bl[r]-1)+1; i<=r; i++) if (a[i]+tag[bl[i]]<x) ans++; for (int i=bl[l]+1; i<=bl[r]-1; i++) ans+=lower_bound(ve[i].begin(),ve[i].end(),x-tag[i])-ve[i].begin(); return ans; } int main() { freopen("easy.in","r",stdin); freopen("easy.out","w",stdout); scanf("%d%d",&n,&m); block=sqrt(n); for (int i=1; i<=n; i++){ scanf("%d",&a[i]); bl[i]=(i-1)/block+1; ve[bl[i]].push_back(a[i]); } for (int i=1; i<=bl[n]; i++) sort(ve[i].begin(),ve[i].end()); while (m--){ char st[5]; int l,r,x; scanf("%s%d%d%d",st,&l,&r,&x); if (st[0]=='Q'){ printf("%d ",query(l,r,x)); } else { change(l,r,x); } } return 0; }