首页 > 其他分享 >【分块】LibreOJ 6282 数列分块入门6

【分块】LibreOJ 6282 数列分块入门6

时间:2024-11-30 16:33:27浏览次数:5  
标签:6282 LibreOJ 分块 int 元素 len num sqrt

题目

https://loj.ac/p/6282

题解

数据范围 \(1 \leq n \leq 10^5\),因此进行分块最多分 \(\sqrt{10^5} ≈ 318\) 块。且数据是随机生成的,因此插入数据后,每个块的长度期望值为 \(\frac{318+(318 + 100000/318)}{2} ≈ 475\)。因此,可以使用分块思想解决该问题。

对于每个块,都用一个数组维护,并且维护每个块的元素个数。

对于查询操作,从第一块开始累计元素的个数,易知该步骤的时间复杂度为 \(O(\sqrt{n})\)。当找出 \(a_r\) 所在的块的时候,直接取出该元素即可。

对于插入操作,先查询出要插入的元素是需要插入到第几个块,该步操作时间复杂度 \(O(\sqrt{n})\),随后使用插入排序的思想进行插入,由于每个块的块长期望为 \(\sqrt{n}\) 级别,因此该步操作的时间复杂度也是 \(O(\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 = 100327;
int n, op, l, r, c, len;
int a[320][N];//1e5个元素,最多只需要分为317个块

int getPieceSize(int pid) {//获取第pid个块的块长。此处是计算初始块长,添加元素该函数失效
	return min(n, pid * len) - (pid - 1) * len;
}

int main() {
	IOS
	cin >> n;
	len = sqrt(n);//块长,最后一块可能不满len个元素
	int num = 1;//块数
	for (int i = 1; i <= n; ++ i) {
		cin >> a[num][i % len];
		if (i % len == 0) {
			a[num][len] = a[num][0];
			++ num;
		}	
	}
    //把每个块的元素个数存储在a[i][0]
	for (int i = 1; i <= num; ++ i) a[i][0] = getPieceSize(i);
	for (int i = 0; i < n; ++ i) {
		cin >> op >> l >> r >> c;
		if (op) {//询问 a[r] 的值
			for (int i = 1, j = 0; i <= num; ++ i) {
				if (j + a[i][0] < r) j += a[i][0];
				else {
					cout << a[i][r - j] << '\n';
					break;
				}
			}
		} else {//在第 l 个数字前插入数字 r
			for (int i = 1, j = 0; i <= num; ++ i) {
				if (j + a[i][0] < l) j += a[i][0];
				else {
					for (int k = a[i][0]; k >= l - j; -- k) a[i][k + 1] = a[i][k];
					a[i][l - j] = r;
					a[i][0] ++;
					break;
				} 
			}
		}
	}
	return 0;
}

标签:6282,LibreOJ,分块,int,元素,len,num,sqrt
From: https://www.cnblogs.com/RomanLin/p/18560549

相关文章

  • 24/11/30 ABC381+莫队+分块+整体二分学习笔记
    [ABC381D]好题。由于题目描述中提到了取出的子序列长度必须是偶数个,所以可以考虑对于原来的\(a\)序列每次进行长度为\(2\)的尺取,这时候不难发现对于开头位置具有两个答案,一个是从\(1\)为开头,一个是从\(2\)为开头,所以写个函数封装一下就好了,类似这种cout<<max(solve(1),solve(2......
  • P2801 教主的魔法 ——分块
    教主的魔法题目描述教主最近学会了一种神奇的魔法,能够使人长高。于是他准备演示给XMYZ信息组每个英雄看。于是\(N\)个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为\(1,2,\ldots,N\)。每个人的身高一开始都是不超过\(1000\)的正整数。教主的魔法每次可以把闭......
  • 关于Ynoi经典分块杂谈
    静态区间逆序对,区间众数P5046[Ynoi2019模拟赛]YunolovessqrttechnologyI强制在线区间逆序对,做法是预处理,然后整块散块分开算贡献,复杂度刚好平衡,常数很大,比较卡常。P5047 [Ynoi2019模拟赛]YunolovessqrttechnologyII区间逆序对离线做法,二次离线模板,常数很小也比序......
  • Trick-整除分块(数论分块)
    整除分块:对于类似于\(solve_{d=1}^{n}(\frac{n}{d})\)的式子,\(\frac{n}{d}\)的值的个数不超过\(\sqrtn\)个(下面有证明),故可以对于每一个结果去计算其贡献。代码如下:voidcalc(intn){for(intl=1,r;l<=n;l=r+1){r=n/(n/l);//d在区间[l,r]的n......
  • 【分块】LibreOJ 6281 数列分块入门5
    前言对一个int类型的非负整数进行开方下取整,最多只会开方四次大小就不会再发生变化。一个大于\(0\)的正整数开方下取整最后的结果比如是\(1\),而\(1\)开方的结果仍然会是\(1\);\(0\)开方的结果仍是\(0\)。验证int类型整数最多可以开方的次数的demo#include<bits/stdc+......
  • 【分块】LibreOJ 6280 数列分块入门4
    题目https://loj.ac/p/6280题解将\(n\)个元素的数组\(a\)按块长\(\sqrt{n}\)进行分块处理。为每个块设置两个懒添加标记\(add[i],sum[i]\),分别代表这个区间每个元素共同添加的数值大小,区间和(不包括懒添加的值)。对于区间加操作,将添加值存储在符合整块都进行加法操作的......
  • 【分块】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个元素,并且连续访问,......
  • 分块
    分块简单理解一下,分块就是优雅的暴力。分块的分类静态分块(只做查询,预处理):静态分块指的是放一些关键点,预处理关键点到关键点的信息,来加速查询的,不能支持修改。目前认为,如果可以离线,静态分块是莫队算法的子集。动态分块(支持修改和查询):动态分块指的是把序列分为一些块,每块......