首页 > 其他分享 >分块

分块

时间:2024-02-17 21:03:06浏览次数:27  
标签:orz 分块 int sum len add long

分块的思想就是将一大段数据分成若干个整段来达到快速维护和查询的效果。运用了懒标记的思想。

最简单的例子如题 一个简单的整数问题

#include <cstdio>
#include <cmath>
#define orz(i,a,b) for (int i = a;i <= b; i++)
#define sto(i,a,b) for (int i = a;i >= b; i--)
using namespace std;
const int N = 2e5 + 5, M = 500 + 5;
int n, m;
long long a[N], add[M], sum[M];//add为懒标记,sum[i]为第 i 块中所有数的总和。a[i]的真实值为a[i]+add[p[i]] 
int p[N], len;//p[i]是i所对块的编号,len是每个块的长度 
void change (int l, int r, long long d) {//修改操作 
	if (p[l] == p[r]) {    //l,r处于同一块之中 
		orz (i, l, r) {    //暴力处理 
			a[i] += d;
			sum[p[i]] += d;
		}
	}
	else {
		int i = l, j = r;
		while (p[i] == p[l]) {//左右零散的用暴力处理 
			a[i] += d;
			sum[p[i]] += d;
			i++;
		}
		while (p[j] == p[r]) {
			a[j] += d;
			sum[p[j]] += d;
			j--;
		}
		orz (k, p[i], p[j]) {//整块的就打上懒标记 
			sum[k] += len * d;
			add[k] += d;
		}
	}
}
long long query(int l, int r) {//查询操作 
	long long ans = 0;
	if (p[l] == p[r]) {//l,r处于同一块 
		orz (i, l, r)  //暴力求解 
			ans += a[i] + add[p[i]];
	}
	else {
		int i = l, j = r;
		while (p[i] == p[l]) {//左右的零散用暴力累加 
			ans += a[i] + add[p[i]];//注意真实值为a[i]+add[p[i]] 
			i++;
		}
		while (p[j] == p[r]) {
			ans += a[j] + add[p[j]];
			j--;
		}
		orz (k, p[i], p[j])//整块的直接加sum 
			ans += sum[k];
	}
	return ans;
}
int main() {
	scanf ("%d%d", &n, &m);
	len = sqrt(n);
	orz (i, 1, n) {
		scanf ("%lld", a + i);
		p[i] = (i - 1) / len;//(i-1)/len使得每一块(除最后一块)都有len个数 
		sum[p[i]] += a[i];
	}
	while (m--) {
		char op;
		scanf (" %c", &op);//%c前加' '可以过滤空格和换行等字符 
		if (op == 'C') {
			int l, r;
			long long k;
			scanf ("%d%d%lld", &l, &r, &k);
			change(l, r, k);
		}
		else {
			int l, r;
			scanf ("%d%d", &l, &r);
			printf ("%lld\n", query(l, r));
		}
	}
	return 0;
}

因为每一块最多为 $\sqrt{N}$ ,所以所有散块的暴力操作时间复杂度为 $O(\sqrt{N})$ 又因为总共只有 $\sqrt{N}$ 块,所以整块的操作时间复杂度也为 $O(\sqrt{N})$ ,所以整个算法的时间复杂度为 $O(M\sqrt{N})$。

标签:orz,分块,int,sum,len,add,long
From: https://www.cnblogs.com/Assassins-Creed/p/18018387

相关文章

  • 分块与莫队算法
    1.分块分块的思想分块是把一个长度为\(N\)的数列分为\(\sqrt{N}\)个块,每个块的长度为\(\sqrt{N}\)。这样在区间操作的时候,对于每个涉及到的块,如果涉及到半个块,就直接操作;如果涉及到整个块,就整体操作。下面通过例题来了解一下分块。例1洛谷-P3372这道题可以用分块来做......
  • [算法学习笔记02]分块应用
    #[算法学习笔记02]分块应用###每日蒟蒻小故事(1/1)蒟蒻考完CSP回到S1,开始(和S2一起)新一轮的S组学习。第一周,学校学习的内容是分块应用。蒟蒻尝试听懂,并听懂了$\huge\frac{1}{3}$的内容。被五年级小朋友吊打的蒟蒻想学懂分块应用。“所以……什么是分块应用呢?”###什......
  • 整除分块
    常搭配莫反食用。莫比乌斯反演笔记P2261余数求和求\(\displaystyle\sum_{i=1}^nk\bmodi\),\(n,k\le1e9\)。第一步:\(k\bmodi=k-i\cdot\lfloor\dfrac{k}{i}\rfloor\),\(\text{原式}=\displaystyle\sum_{i=1}^nk-i\cdot[\frac{k}{i}]\).第二步:\(\text{原式}=nk-\displayst......
  • 数论分块
    将O(n)优化成o(根号n)[CQOI2007]余数求和题目描述给出正整数\(n\)和\(k\),请计算\[G(n,k)=\sum_{i=1}^nk\bmodi\]对于\(100\%\)的数据,保证\(1\leqn,k\leq10^9\)voidsolve(){ intn,k;cin>>n>>k; intans=n*k; //注意推导公式字母不要弄混 for(int......
  • 莫队算法/分块思想
    莫队算法/分块思想引入对于区间问题,常常会使用线段树维护,但是对于一些数据合并复杂度无法\(O(1)\)解决。所以不能使用,应当使用莫队算法。定义对于离线处理的查询问题,通过合理安排这些计算的次序,得到一个较优的复杂度例题1一个长度为\(n\)的序列,询问\(m\)次\([L,R]\)......
  • 一对一视频app开发,如何分块加载大文件?
    一对一视频app开发,如何分块加载大文件?后端:使用Koa2实现分块传输首先,在一对一视频app开发中,我们需要设置后端以支持分块传输编码。以下是使用Koa2的示例代码:constKoa=require("koa");constfs=require("fs");constapp=newKoa();app.use(async(ctx)=>......
  • 数论分块
    数论分块算法简介能够在\(\mathcal{O(\sqrt{n})}\)的时间复杂度内计算出含有\(\sum\limits_{i=1}^{n}\left\lfloor\frac{k}{i}\right\rfloor\)等式子。令\(a_i=\left\lfloor\frac{k}{i}\right\rfloor\),其主要思想为显然存在若干段连续区间内\(a_i\)值相同,......
  • P5048 [Ynoi2019 模拟赛] Yuno loves sqrt technology III(分块)
    题意简述多次询问区间众数的出现次数,强制在线。\(n,m\le5\times10^5\),时限\(2\)秒,空限\(62.5\)MB。分析弱化版本题相较弱化版有以下特点:空间复杂度要求\(O(n)\)时间复杂度要求严格\(O(n\sqrtn)\),也就是说\(O(n\sqrt{n\logn})\)过不掉。貌似所有5e5的分块都是......
  • Ybt 金牌导航 6.3.A. 区间众数 / P4168 [Violet] 蒲公英(分块)
    题意简述多次查询区间\([l,r]\)的众数,若有多个取数值最小的。强制在线。\(n\le4\times10^4,m\le5\times10^4\)。分析考虑分块。首先预处理出块区间内的众数\(maj_{l,r}\)和每种数在某个块的前缀的出现次数\(cnt_{i,a_i}\),时空复杂度都是\(O(n\sqrtn)\)的。对于询......
  • 【Django】通用分块上传
    通用分块上传文件importos#通用路径分块上传defpiecemeal_public_load(path,original_md5_hash,chunk_index,upload_file,chunk_total,file_Name):"""path:存放路径(media/后面跟的路径)original_md5_hash:临时文件夹名称chunk_inde......