0
点赞
收藏
分享

微信扫一扫

数列分块入门 1 (单点查值,区间加法)

sin信仰 2022-04-13 阅读 40
算法

描述:

给出一个长为n 的数列,以及 n 个操作,操作涉及区间加法,单点查值。

输入:

第一行输入一个数字n。
第二行输入n个数字,第i个数字为ai,以空格隔开。
接下来输入n行询问,每行输入四个数字opt,l,r,c,以空格隔开。
若opt=0,表示将位于[l,r]的之间的数字都加c。
若opt=1,表示询问ar 的值(l和c忽略)。

输出:

对于每次询问,输出一行一个数字表示答案。

int len=sqrt(n);//块长
int add[N];//每个块要加的元素
block[i] //第 i 个元素所在的块的编号
len*block[i]//第 i 个块的右边界
(block[i]-1)*len+1//第 i 个块的左边界
block[i]=(i-1)/len+1;//元素与块编号对应关系
#include<bits/stdc++.h>
using namespace std;
 
typedef unsigned long long ull;
typedef long long ll;
 
const ll maxx = 1e18;
const int N = 1e5+100;
const int p = 1e4;
const double eps = 1e-8;

int n;
int a[N],block[N];
int len;//块长 
int add[N];

void Add(int l,int r,int c)
{ 	
	for(int i=l;i<=min(r,len*block[l]);i++)
		a[i]+=c;//处理左边非整块
		
	if(block[l]!=block[r])
		for(int i=(block[r]-1)*len+1;i<=r;i++)
			a[i]+=c;//处理右边非整块
			
	for(int i=block[l]+1;i<=block[r]-1;i++)
		add[i]+=c;//处理中间的整块	
	
}

void query(int x)
{
	printf("%d\n",a[x]+add[block[x]]);
}//查询

int opt,l,r,c;

int main()
{
	cin>>n;
	
	len=sqrt(n);
	
	
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		block[i]=(i-1)/len+1;
	}

	
	for(int i=1;i<=n;i++)
	{
		cin>>opt>>l>>r>>c;
		
		if(opt==0) Add(l,r,c);
		else query(r);
		
	}	
}

举报

相关推荐

0 条评论