数列分块 1 ~ 9

如果还不了解什么是分块,清先阅读分块link这一篇文章

【题目1】:

描述 : 给出一个长为(n)的数列,以及(n)个操作,操作涉及区间加法,单点查值 , 题目[link]: QwQ

【题目思路】:

首先看到这个题,是可以有很多思路的,这道题几乎涉及很多的数据结构问题模板,但是主要这里主要讲解为数列分块

其实早就予以给出了什么是分块,我们也是可以类比一下线段树, 我们用一个个的块来维护,我们用(lazy)来记录一下它的加法标记,这样也就不必要进行下传,如果是那样下穿的,恭喜你,你分了个锤子,时间复杂度不减反升(因为你还需要处理块呀) ,

【code】:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map> 
#define int long long
#define QwQ printf("运行过了
") ;
#define inf 0x3f 
using namespace std;
const int maxn = 50000 + 10 ;
inline int read()
{
	int x = 0 , f = 1 ; char ch = getchar() ;
	while(!isdigit(ch)){ if(ch == '-') f = - 1 ; ch = getchar() ; }
	while( isdigit(ch)){ x = x * 10 + ch - '0' ; ch = getchar() ; }
	return x * f ;
} 
int n , st ;
int num[maxn] , block[maxn] , lazy[maxn];
void add(int a , int b , int c)
{
	for(int i = a ; i <= min(block[a] * st , b) ; i++)
	{
		num[i] += c ; 
	}
	if(block[a] != block[b])
	{
		for(int i = (block[b] - 1) * st + 1 ; i <= b ; i++)
		{
			num[i] += c ;
		}
	}
	for(int i = block[a] + 1 ; i <= block[b] - 1 ; i++)
	{
		lazy[i] += c ;
	}
}
signed main()
{
	n = read() ; st = sqrt(n) ;
	for(int i = 1 ; i <= n ; i++)
	{
		num[i] = read() ;
	}
	for(int i = 1 ; i <= n ; i++)
	{
		block[i] = (i - 1) / st + 1 ;
	}
	for(int i = 1 ; i <= n ; i++)
	{
		int opt = read() , l = read() , r = read() , c = read() ;
		if(opt == 0) add( l , r , c) ;
		if(opt == 1) printf("%d
" , num[r] + lazy[block[r]]) ;
	}
 	return 0 ;
}

原文地址:https://www.cnblogs.com/Zmonarch/p/14198908.html