如果还不了解什么是分块,清先阅读分块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 ;
}