首页 > 其他分享 >分块

分块

时间:2024-08-05 22:28:52浏览次数:10  
标签:matrix 分块 int 查询 修改 cdots

写在前面

非常简单的分块,使我开心的转圈,稍微看了一下 oi wiki 就懂了,妈妈再也不用担心我的暴力了

正文

分块,非常优雅的暴力,本质是上是通过对原数据的适当划分,并在划分后的每一个块上预处理部分信息,从而较一般的暴力算法取得更优的时间复杂度。
例如(博客萌新好不容易整的)

\[\begin{matrix} \underbrace{ a_1+a_2+\cdots+a_s } \\ k_1 \end{matrix} \begin{matrix} \underbrace{ a_{s+1}+a_{s+2}+\cdots+a_{2s} } \\ k_2 \end{matrix} \cdots\begin{matrix} \underbrace{ a_{(s+1)\times s+1}+\cdots+a_{n} } \\ k_\tfrac{n}{s} \end{matrix}\]

\(n\) 如果不是s的倍数最后一个块可能不完整,但也没关系,对最后操作无影响

查询操作

如果负责查询的 \(l,r\) 都在同一个块中,暴力枚举 \(l\) 到 \(r\)
如果 \(l\) 或 \(r\) 不在所在块的头或尾,则暴力将 \(l\) 和 \(r\) 枚举到块的头或尾部
然后再从 \(l\) 所在的整块枚举整快到 \(r\) 所在的整块,将所有查询结果加和,即为结果

修改操作

和查询操作的思路一样
就是在整块修改时,无法依次修改块中元素,需要在修改时打个 \(add[]\) 标记,存储整块 \(k[]\) 的值被修改了,而单点 \(a[]\) 却没有被修改的数值,在查询单点 \(a[]\) 时加上标记就行

警示后人

在判断第 \(i\) 个数属于哪个块时,要注意对于任意一个块 \(k[j]\) (为了简单举 \(j=1\) 的例子)的下标为 \(1,2,3 \cdots,s\)
然而 \(1,2,3 \cdots,s-1\) 的下标 \(i\) 进行对应块的下标却为 \(\tfrac{i}{s}+1\) ,要记得特判

代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+5;
int a[N],k[N],add[N];
int n,s,cnt,m,op,u,v,ad;
int id(int x){
	if(x%s==0)  return x/s;
	return x/s+1;
} 
void change(int x,int y,int ad){
	if((id(x))==(id(y))){
		for(int i=x;i<=y;i++){
			a[i]+=ad;
		}
		k[id(x)]+=ad*(y-x+1);
		return;
	}
	while(x%s!=1){
		a[x]+=ad;
		k[id(x)]+=ad;
		x++;
	}
	while(y%s!=0){
		a[y]+=ad;
		k[id(y)]+=ad;
		y--;
	}
	for(int i=id(x);i<=id(y);i++){
		k[i]+=ad*s;
		add[i]+=ad;
	}
}
int query(int x,int y){
	int res=0;
	if(id(x)==id(y)){
		for(int i=x;i<=y;i++){
			res+=a[i]+add[id(i)];
		}
		return res;
	}
//	printf("nsbsbnsbs\n");
	while(x%s!=1){
	//	printf("x=%d\n",x);
		res+=a[x]+add[id(x)];
		x++;
	//	printf("res=%d\n",res);
	}
	while(y%s!=0){
//		printf("y=%d\n",y);
		res+=a[y]+add[id(y)];
		y--;
//		printf("res=%d\n",res);
	}
//	printf("x=%d y=%d\n",x,y);
	for(int i=id(x);i<=id(y);i++){
		res+=k[i];
//		printf("res=%d\n",res);
	}
	return res;
}
signed main(){
	scanf("%lld%lld",&n,&m);
	s=(int)sqrt(n);
	for(int i=1;i<=n;i++){
		scanf("%lld",&a[i]);
		if(i%s==1){
			cnt++;
		}
		k[cnt]+=a[i];
	}
//	for(int i=1;i<=cnt;i++){
//		printf("%d ",k[i]);
//	}
//	printf("\nlll\n");
	for(int i=1;i<=m;i++){
		scanf("%lld%lld%lld",&op,&u,&v);
		if(op==1){
			scanf("%lld",&ad);
			change(u,v,ad);
		}
		else{
			printf("%lld\n",query(u,v));
		}
	}
}

标签:matrix,分块,int,查询,修改,cdots
From: https://www.cnblogs.com/zcxnb/p/18344171

相关文章

  • 《Advanced RAG》-05-探索语义分块(Semantic Chunking)
    摘要文章首先介绍了语义分块在RAG中的位置和作用,并介绍了常见的基于规则的分块方法。然后,阐述了语义分块的目的是确保每个分块包含尽可能多的独立语义信息。接着,文章分别介绍了三种语义分块方法的原理和实现方法,并对每种方法进行了总结和评估。文章观点语义分块是R......
  • 数据结构——数列分块 学习笔记
    数据结构——数列分块学习笔记下面部分代码使用,usingll=longlong;#defineintll基础思想问题引入问题:实现区间加;区间求和。基本结构引用经典东西,我们考虑构造一个结构,形如,那么,结论是,复杂度证明为什么块长一般是\(\sqrtn\)呢?我们假设构造的块长是\(......
  • LLM 大模型文档语义分块、微调数据集生成
    1、LLM大模型文档语义分块参考:https://blog.csdn.net/m0_59596990/article/details/140280541根据上下句的语义相关性,相关就组合成一个分块,不相关就当场两个快语义模型用的bert-base-chinese:https://huggingface.co/google-bert/bert-base-chinese代码:对水浒传的分......
  • 洛谷P2801 教主的魔法之分块板子
    洛谷P2801题解传送锚点摸鱼环节教主的魔法题目描述教主最近学会了一种神奇的魔法,能够使人长高。于是他准备演示给XMYZ信息组每个英雄看。于是\(N\)个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为\(1,2,\ldots,N\)。每个人的身高一开始都是不超过\(1000\)......
  • 将 HTTP 分块编码数据流代码片段从 Node.js 转换为 Python
    我有一个Node.js客户端代码,它将请求发送到HTTP服务器,然后连续接收分块编码数据。这是带有一些流量数据输出的Node.js代码。consthttp=require('http');constoptions={hostname:'...',path:'...',port:...,...};constreq=http.request(......
  • Contest7506 - 莫队 分块
    ContestA至少重复三次的数字莫队板子。B小明的习题集洛谷原题P1494[国家集训队]小Z的袜子。C棋子的颜色洛谷原题P1903[国家集训队]数颜色/维护队列。带修莫队:普通莫队是二维问题,现在加上一维时间轴,做法基本上同普通莫队。对询问\((l,r,t)\)排序时,第一关键......
  • 分块矩阵方法
    分块矩阵法是高等代数中处理矩阵相关问题的最重要的方法之一,其重要性可以说怎么强调都不过分.分块矩阵法的核心思想是根据具体问题构造适当的分块矩阵,然后运用广义初等变换,将某些子块消为零块,得到特殊的分块矩阵从而解决问题.该方法几乎贯穿了线性代数的始终,在矩阵求......
  • 基础数论 整除分块与欧拉函数
    整除分块:例题:已知\(f(n)=\sum\limits_{i=1}^{n}\left\lfloor\frac{n}{i}\right\rfloor\),给定\(n\),求\(f(n)\)的值。固然可以\(O(n)\)暴力,但显然会\(TLE\)。计算一下前几项的值之后可以发现\(\left\lfloor\frac{n}{i}\right\rfloor\)的取值在连续的一段区间内是......
  • 分块:优雅的暴力
    分块是一种思想,通过对原数据的适当划分,并在划分后的每一个块上预处理部分信息,从而较一般的暴力算法取得更优的时间复杂度。分块的应用面十分广泛,包括但不限于数组、树形结构等。1.块状数组块状数组是分块思想最简单的应用。它将一个数组分成若干块,然后对数组进行区间操作。对......
  • 分块
    分块数列分块入门4区间修改区间查询区间修改正常。但是区间查询有几个需要注意的点:1.需要取模。(这里对喜欢疯狂取模的人我提个醒:千万不要在bl[l]=...那里取模啊,把块数给模了就完全错了,还有一些不能模的地方一定要看清楚!!!)2.用懒标记算答案的时候一定要乘上r-l+1,别单点......