题目链接
题目描述
给出一个长为 的数列,以及 个操作,操作涉及区间加法,询问区间内小于某个值 的元素个数。
输入格式
第一行输入一个数字n 。
第二行输入n 个数字,第 i 个数字为ai ,以空格隔开。
接下来输入n 行询问,每行输入四个数字op 、l、r、c,以空格隔开。
若 op=0,表示将位于 [l,r] 的之间的数字都加c 。
若 op=1,表示询问 [l,r]中,小于c2 的数字的个数。
输出格式
对于每次询问,输出一行一个数字表示答案。
解题思路
这个题如果用线段树写的话就会很麻烦,但是用分块写就比较容易实现了。
用一个数组b[] 对每一块块内的数进行排序,因为排序过了之后,每次查找的时候,查找块内的数就会很容易。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
using namespace std;
const int maxn=5e4+7;
int a[maxn],belong[maxn],r[maxn],l[maxn],b[maxn],lazy[maxn],block,num,n,m;
void init()
{
block=sqrt(n);
num=n/block;
if(n%block)
num++;
for(int i=1; i<=n; i++)
belong[i]=(i-1)/block+1;
for(int i=1; i<=n; i++)
{
l[i]=(i-1)*block+1;
r[i]=i*block;
}
//printf("%d\n",block);
for(int i=1; i<=block; i++)
sort(b+l[i],b+min(r[i],n)+1);
}
void update(int ll,int rr,int v)
{
if(belong[ll]==belong[rr])
{
for(int i=ll; i<=rr; i++)
a[i]+=v;
for(int i=l[belong[ll]];i<=min(r[belong[ll]],n);i++)
b[i]=a[i];
sort(b+l[belong[ll]],b+min(r[belong[ll]],n)+1);
}
else
{
for(int i=ll; i<=r[belong[ll]]; i++)
a[i]+=v;
for(int i=l[belong[ll]]; i<=min(r[belong[ll]],n); i++)
b[i]=a[i];
sort(b+l[belong[ll]],b+min(r[belong[ll]],n)+1);
for(int i=belong[ll]+1; i<belong[rr]; i++)
lazy[i]+=v;
for(int i=l[belong[rr]]; i<=rr; i++)
a[i]+=v;
for(int i=l[belong[rr]]; i<=min(r[belong[rr]],n); i++)
b[i]=a[i];
sort(b+l[belong[rr]],b+min(r[belong[rr]],n)+1);
}
}
int que(int ll,int rr,int v)
{
int ans=0;
if(belong[ll]==belong[rr])
{
for(int i=ll; i<=rr; i++)
{
if(a[i]+lazy[belong[ll]]<v)
ans++;
}
}
else
{
for(int i=ll; i<=belong[ll]*block; i++)
{
if(a[i]+lazy[belong[ll]]<v)
ans++;
}
for(int i=belong[ll]+1; i<belong[rr]; i++)
{
int cnt=v-lazy[i];
ans+=lower_bound(b+l[i],b+r[i]+1,cnt)-b-l[i];
}
for(int i=(belong[rr]-1)*block+1; i<=rr; i++)
{
if(a[i]+lazy[belong[rr]]<v)
ans++;
}
}
return ans;
}
int main()
{
int x,y,z,p;
scanf("%d",&n);
for(int i=1; i<=n; i++)
{
scanf("%d",&a[i]);
b[i]=a[i];
}
//printf("***");
init();
for(int i=1; i<=n; i++)
{
scanf("%d %d %d %d",&p,&x,&y,&z);
if(p==0)
update(x,y,z);
else
printf("%d\n",que(x,y,z*z));
}
return 0;
}