首页 > 其他分享 >【分块】LibreOJ 6280 数列分块入门4

【分块】LibreOJ 6280 数列分块入门4

时间:2024-11-26 23:54:45浏览次数:9  
标签:LibreOJ 分块 int 复杂度 6280 sqrt 添加 ll

题目

https://loj.ac/p/6280

题解

将 \(n\) 个元素的数组 \(a\) 按块长 \(\sqrt{n}\) 进行分块处理。为每个块设置两个懒添加标记 \(add[i], sum[i]\),分别代表这个区间每个元素共同添加的数值大小,区间和(不包括懒添加的值)。

对于区间加操作,将添加值存储在符合整块都进行加法操作的块的懒标记 \(add[i]\) 上,单次操作时间复杂度 \(O(1)\),此类块至多只有 \(\sqrt{n}\) 块,最差时间复杂度 \(O(\sqrt{n})\);未符合整块的进行加法操作则进行暴力处理,即为下标位于 \([l, r]\) 的元素直接添加上 \(c\),单次操作时间复杂度 \(O(\sqrt{n})\),此类块至多只有 \(2\) 块,最差时间复杂度 \(O(2\sqrt{n})\)。

对于区间和操作,将覆盖到的整块的 \(sum[i]\) 直接添加到结果中,并且添加当前块大小乘以 \(add[i]\) 到结果中。单次操作时间复杂度 \(O(1)\),此类块至多只有 \(\sqrt{n}\) 块,最差时间复杂度 \(O(\sqrt{n})\);未符合整块的进行区间和操作则进行暴力处理,即下标位于 \([l, r]\) 的元素直接添加上 \(c\),单次操作时间复杂度 \(O(\sqrt{n})\),此类块至多只有 \(2\) 块,最差时间复杂度 \(O(2\sqrt{n})\)。

参考代码

#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
using namespace std;

typedef long long ll;
constexpr int N = 50007;
int n, op, l, r, c;
int len;//块长
ll a[N];//数列
ll add[230];//懒添加标记
ll sum[230];//块和

/*初始化块*/
void initPieces() {
	len = sqrt(n);
	for (int i = 1, j = 1; i <= n; ++ i) {
		sum[j] += a[i];
		if (i % len == 0) ++ j;
	}
}

/*获取下标 x 所在的块的索引*/
int getPieceId(int x) {
	return (x - 1) / len + 1;
}

/*获取第 pid 块的大小,即这个块的元素个数*/
int getPieceSize(int pid) {
	return min(n, pid * len) - (pid - 1) * len;
}

/*判断下标 x 是否为块的左边界*/
bool isLeftBoundary(int x) {
	return (x - 1) % len == 0;
}

/*判断下标 x 是否为块的右边界*/
bool isRightBoundary(int x) {
	return x % len == 0;
}

int main() {
	IOS
	cin >> n;
	for (int i = 1; i <= n; ++ i) cin >> a[i];
	initPieces();
	for (int i = 0; i < n; ++ i) {
		cin >> op >> l >> r >> c;
		bool isLe = isLeftBoundary(l), isRi = isRightBoundary(r);
		int le = getPieceId(l), ri = getPieceId(r);
		if (op) {//区间和
			++ c; 
			ll res = 0LL;
			for (int i = isLe ? le : le + 1, j = isRi ? ri : ri - 1; i <= j; ++ i) {
				res = (res + sum[i] % c + add[i] * getPieceSize(i) % c) % c;
			}
			if (!isLe) {
				while (l <= r) {
					res = (res + add[le] + a[l]) % c;
					if (isRightBoundary(l)) break;
					++ l;
				}
			}
			if (!isRi) {
				while (l <= r) {
					res = (res + add[ri] + a[r]) % c;
					if (isLeftBoundary(r)) break;
					-- r;
				}
			}
			cout << res << '\n';
		} else {//区间加
			for (int i = isLe ? le : le + 1, j = isRi ? ri : ri - 1; i <= j; ++ i) add[i] += c;
			if (!isLe) {
				while (l <= r) {
					a[l] += c;
					sum[le] += c;
					if (isRightBoundary(l)) break;
					++ l;
				}
			}
			if (!isRi) {
				while (l <= r) {
					a[r] += c;
					sum[ri] += c;
					if (isLeftBoundary(r)) break;
					-- r;
				}
			}
		}
	}
	return 0;
}

标签:LibreOJ,分块,int,复杂度,6280,sqrt,添加,ll
From: https://www.cnblogs.com/RomanLin/p/18560154

相关文章

  • 【分块】LibreOJ 6278 数列分块入门2
    题目https://loj.ac/p/6278题解将\(n\)个元素的数组\(a\)按块长\(\sqrt{n}\)进行分块处理。为每个块设置一个懒添加标记\(add[i]\),代表这个区间每个元素共同添加的数值大小。对于任意一个无序数组,想要维护出该数组内小于某个值的元素个数,时间复杂度都将来到\(O(n)\);对......
  • 【分块】LibreOJ 6279 数列分块入门3
    题目https://loj.ac/p/6279题解将\(n\)个元素的数组\(a\)按块长\(\sqrt{n}\)进行分块处理。为每个块设置一个懒添加标记\(add[i]\),代表这个区间每个元素共同添加的数值大小。对于任意一个无序数组,想要维护出该数组内某个值的前驱(即小于某个值的最大元素),时间复杂度都将......
  • 高性能计算-探究循环分块优化(2-1)
    1.目标:分析循环分块优化技术,并分析cache命中情况假设每个cacheline可以存储b个数据元素。2.源代码分析for(inti=0;i<N;i++){ for(intj=0;j<M;j++) { A[i]+=B[j]; }}cachemiss分析:对A总访问次数为NM,每次访存加载一个cacheline可以加载b个元素,并且连续访问,......
  • 分块
    分块简单理解一下,分块就是优雅的暴力。分块的分类静态分块(只做查询,预处理):静态分块指的是放一些关键点,预处理关键点到关键点的信息,来加速查询的,不能支持修改。目前认为,如果可以离线,静态分块是莫队算法的子集。动态分块(支持修改和查询):动态分块指的是把序列分为一些块,每块......
  • 408数据结构-折半查找,分块查找 自学知识点整理
    前置知识:查找的基本概念折半查找折半查找又称二分查找,它仅适用于有序的顺序表。因个人习惯,下文均用二分代替折半。二分查找的基本思想:首先将给定值ke......
  • 【JS】requestIdleCallback实现分块执行
    点击按钮后,执行一个耗时较长的dom操作,页面很长时间没有响应,给用户一种卡死的现象<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,initial-scale=1.0">&......
  • 张量矩阵乘法分块乘法概述
    张量矩阵乘法分块乘法概述介绍一下矩阵计算相关的内容,从最基本的算法,到Cutlass这些线性代数模版库,特别是Layout代数相关的内容,再逐渐细化到一些硬件实现访存优化和一些算子融合。6.3.1GEMM概述1.GEMM定义对于一个矩阵乘法,定义如下: (6-1)一个矩阵乘法定义,如图6-26......
  • P3863 序列(分块)
    感觉是一个比较厉害的trick,并且从来没见过,记录一下。题意给定\(n\)个数和\(q\)次操作:1lrx:区间\([l,r]\)加\(x\)。2xv:查询在询问之前有多少时刻\(a_x\gev\)。一次操作定义为一个时刻,初始为\(0\)时刻。\(n,q\le10^5\)分析如果\(x\ge0\),那么\(a_i\)的......
  • P3730 曼哈顿交易(经典题,莫队+值域分块)
    记录这一类很典的题目。题意给定\(n\)个数,\(q\)次询问区间\([l,r]\)内出现次数第\(k\)小的数的出现次数。若区间内不同数的个数小于\(k\)输出-1。\(n,q\le10^5\)。分析发现正常的数据结构以及分块都很难维护这种信息,考虑莫队。莫队加入数时,我们需要更新一个数的......
  • 分块式内存管理理论理解
    一,引入             分块式内存管理是一种内存管理策略,它将内存划分为若干个大小相等的块(称为“分区”、“段”或“块”),然后为不同的程序分配这些块。这种策略可以有效地解决内存碎片问题,提高内存利用率。分块式内存管理通常有两种实现方式:固定大小块和可变......