数列分块入门 2 LibreOJ - 6278------------------分块

数列分块入门 2 LibreOJ - 6278------------------分块_第1张图片

数列分块入门 2 LibreOJ - 6278------------------分块_第2张图片
解析:
对于区间加法:
我们暴力计算哪些不完整的块
对于完整的块用懒惰标记记录

对于区间查询 ,查小于x2 d的个数
我们可以用b数组copy原序列。
在暴力修改不完整的块时,我们破坏了该块的单调性,所以我们需要给该块重新赋值
重新排序。。 这里可以暴力求解

对于修改完整块的时候,我们二分计算就行了。

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+1000;
int l[N];//第i块左区间端点 
int r[N];//第i块右区间端点
int pos[N];//当前i属于第几块 
int lazy[N];
int n,op,u,v,c;
int a[N],b[N];
void add(int ll,int rr,int v)
{
	int posl=pos[ll];//判断左端点是哪个块
	int posr=pos[rr];//判断右端点是哪个块
	if(posl==posr) //如果同一块直接暴力求和
	{
		for(int i=ll;i<=rr;i++) a[i]+=v; //这样子有可能破坏单调性
		//所以b数组在该块上要重新赋值
		for(int i=l[posl];i<=r[posl];i++) b[i]=a[i];
		//重新排序 
		sort(b+l[posl],b+r[posl]+1); 
		
		
	 } 
	 else
	 {
	 	for(int i=ll;i<=r[posl];i++) a[i]+=v; //暴力修改左侧不完整
		//b数组在该块重新赋值
		for(int i=l[posl];i<=r[posl];i++)  b[i]=a[i];
		//b数组在该块重新排序 
		sort(b+l[posl],b+r[posl]+1);
		
		for(int i=l[posr];i<=rr;i++) a[i]+=v; //暴力修改右侧不完整 
		for(int i=l[posr];i<=r[posr];i++) b[i]=a[i];
		sort(b+l[posr],b+r[posr]+1);
		
		for(int i=pos[ll]+1;i<=pos[rr]-1;i++) lazy[i]+=v; 
		 
	 	
	  } 

}
int query(int ll,int rr,int v)
{
	int posl=pos[ll];//判断左端点属于哪个块 
	int posr=pos[rr];//判断右端点属于哪个块 
	int cnt=0;
	if(posl==posr) 
	{
		for(int i=ll;i<=rr;i++)
		{
			if(a[i]+lazy[posl]<v) cnt++;
		}
		return cnt;
	}
	for(int i=ll;i<=r[posl];i++) //暴力查询左侧不完整的块 
	{
		if(a[i]+lazy[posl]<v) cnt++;
	}
	for(int i=l[posr];i<=rr;i++)//暴力查询右侧不完整的块 
	{
		if(a[i]+lazy[posr]<v) cnt++;
	 } 
	 for(int i=pos[ll]+1;i<=pos[rr]-1;i++)
	 {
	 	cnt+=lower_bound(b+l[i],b+r[i]+1,v-lazy[i])-(b+l[i]);
	  } 
	//  cout<
	  return cnt;
	
	
}
int main()
{
	scanf("%d",&n);
	int dis=sqrt(n);//每个块的大小 
	int num=ceil(1.0*n/dis);//哟多少个块 
	for(int i=1;i<=num;i++) l[i]=(i-1)*dis+1,r[i]=i*dis; 
	r[num]=n;
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		b[i]=a[i];
		pos[i]=(i-1)/dis+1;
	}
	//对每个块排序 
	for(int i=1;i<=num;i++) sort(b+l[i],b+r[i]+1);
	for(int i=1;i<=n;i++)
	{
		scanf("%d %d %d %d",&op,&u,&v,&c);
		if(op==0) add(u,v,c);
		else cout<<query(u,v,c*c)<<endl;
	}
}

你可能感兴趣的:(分块)