题解【loj6277】数列分块入门1
题目描述
给出一个长为\(n\)的数列,以及\(n\)个操作,操作涉及区间加法,单点查值。
输入格式
第一行输入一个数字\(n\)。
第二行输入\(n\)个数字,第\(i\)个数字为\(a_{i}\),以空格隔开。
接下来输入\(n\)行询问,每行输入四个数字\(opt\)、\(l\)、\(r\)、\(c\),以空格隔开。
若\(opt = 0\),表示将位于\([l, r]\)的之间的数字都加\(c\)。
若\(opt = 1\),表示询问\(a_{r}\)的值(\(l\)和\(c\)忽略)。
输出格式
对于每次询问,输出一行一个数字表示答案。
样例
样例输入
4
1 2 2 3
0 1 3 1
1 0 1 0
0 1 2 2
1 0 2 0
样例输出
2
5
数据范围与提示
对于所有的数据,\(1 \leq n \le 50000\) ,\(-2^{31} \leq others、ans \le 2_{31} - 1\) 。
题解
这是一道很好的分块入门题。
所谓分块,就是一种通过将一个序列分成多块后,在每块上打标记以实现快速区间修改,区间查询的一种算法。其均摊时间复杂度为\(\Theta\sqrt{n}\)。
在一般情况下,每个块的长度都为\(\sqrt{n}\)。
分块,被尊称为优雅的暴力,因此它的代码难度也不算高。总之,比线段树、树状数组等毒瘤数据结构的代码难度低。
我们需要建立三个数组:
- \(a[]\),为题目中输入的序列;
- \(b[]\),记录每个序列中的每个数在那一块;
- \(add[]\),为序列的标记数组。
话不多说,上代码。
代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cctype>//头文件准备
using namespace std;//使用标准名字空间
inline int gi()//快速读入
{
int f = 1, x = 0; char c = getchar();
while (c < '0' || c > '9') { if (c == '-')f = -1; c = getchar();}
while (c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar();}
return f * x;
}
int a[50005], b[50005], add[50005], len, n, m;//a[],b[],add[]的意思如分析,len为每一块的长度,n为序列长度,m为询问个数,在本题中=n。
inline void modify(int l, int r, int x)//区间修改的自定义函数
{
for (int i = l; i <= min(r, b[l] * len); i++) a[i] = a[i] + x;//增加序列中的数
if (b[l] != b[r])//如果要修改的不在同一个块中
{
for (int i = (b[r] - 1) * len + 1; i <= r; i++) a[i] = a[i] + x;//继续增加序列中的数
}
for (int i = b[l] + 1; i <= b[r] - 1; i++) add[i] = add[i] + x;//给区间内的数增加标记
}
int main()//进入主函数
{
n = gi();//输入元素个数
len = sqrt(n);//求出每个块的长度
for (int i = 1; i <= n; i++) a[i] = gi();//输入序列中的数
for (int i = 1; i <= n; i++) b[i] = (i - 1) / len + 1;//求出序列中的数分别属于哪一个块
for (int p = 1; p <= n; p++)
{
int fl = gi(), l = gi(), r = gi(), w = gi();//输入操作的描述
if (!fl)//如果是修改
{
modify(l, r, w);//修改区间内的数
}
else//否则就是求出某个数
{
printf("%d\n", a[r] + add[b[r]]);//输出这个位置的数的标记和它在序列中原本的数的和
}
}
return 0;//完美结束
}
题解【loj6277】数列分块入门1的更多相关文章
- 题解——loj6277 数列分块入门1(分块)
分块裸题 然后就是记得左右边界处理和分块的初始化 忘了初始化会被卡成暴力 #include <cstdio> #include <algorithm> #include < ...
- 题解——loj6281 数列分块入门5 (分块)
分块 若块内最大值为0或1,则不用再开方 然后暴力修改 可以证明,如果开方后向下取整,则最多开方4次一个数就会变成0或1 #include <cstdio> #include <cm ...
- 题解——loj6280 数列分块入门4 (分块)
分块维护一个区间和 然后记得更新的时候左边角块的tag不要打错到右边角块 #include <cstdio> #include <algorithm> #include < ...
- [LOJ6277]数列分块入门 1
题目大意: 给你一个长度为$n(n\leq 50000)$的序列$A$,支持进行以下两种操作: 1.将区间$[l,r]$中所有数加上$c$: 2.询问$A_r$的值.思路: 分块. 对于整块的数据打标 ...
- loj6277 数列分块入门题1
裸题分块. #include <bits/stdc++.h> using namespace std; ],b[],n,m,t1,t2,t3,t4,sq; int main(){ ios: ...
- 题解——loj6279 数列分块入门3 (分块)
用set维护有序序列 或许sort也可以,但这题的前驱定义是严格小于 所以要去重 然后就是记得自己打的加法tag在query的时候一定要算上 话说这题数据有点fake啊忘了查询算上自己的标记了还有70 ...
- 题解——loj6278 数列分块入门2 (分块)
查询小于k的值 注意lower_bound一定要减去查找的起始位置得到正确的位置 调了快两天 淦 #include <cstdio> #include <algorithm> ...
- LOJ6277~6285 数列分块入门
Portals 分块需注意的问题 数组大小应为,因为最后一个块可能会超出的范围. 当操作的区间在一个块内时,要特判成暴力修改. 要清楚什么时候应该+tag[t] 数列分块入门 1 给出一个长为的数列, ...
- 数列分块入门九题(一):LOJ6277~6279
Preface 分块,一个神奇的暴力算法.可以把很多\(O(n^2)\)的数据结构题的暴力优化到常数极小的\(O(n\sqrt n)\).当一些毒瘤题无法用线段树,主席树,平衡树,树状数组...... ...
- LibreOJ6279. 数列分块入门 3 题解
题目链接:https://loj.ac/problem/6279 题目描述 给出一个长为 \(n\) 的数列,以及 \(n\) 个操作,操作涉及区间加法,询问区间内小于某个值 \(x\) 的前驱(比其 ...
随机推荐
- IO流学习之字符流(三)
IO流之字符流缓冲区: 概念: 流中的缓冲区:是先把程序需要操作的数据保存在内存中,然后我们的程序读写数据的时候,不直接和持久设备之间交互,而改成和内存中的数据进行交互. 缓冲区:它就是临时存储数据, ...
- 为什么MYSQL分页时使用limit+ order by会出现数据重复问题
问题描述: MYSQL采用limit进行翻页查询时,搭配order by ,在翻到第二页的时候可能会出现第一页的数据, 示例sql如下: select a,b from c where d = ' ...
- Tomcat中相关配置详解
tomcat的相关配置 server.xml <Server port="8005" shutdown="SHUTDOWN"> <!-- 属性 ...
- 《UNIX环境高级编程》源码配置——apue.3e 安装
转载从:http://blog.csdn.net/songshimvp1/article/details/51440545 网上大都是针对UNIX高级编程第二版的头文件搭建,现在对于第三版来说有些过时 ...
- 关闭Apache的目录浏览功能
一.默认情况 默认情况下,Apache的配置文件C:\web\apache2.4\conf/httpd.conf中有如下参数: 引用 <Directory "/var/www/html ...
- Python 绘图 cookbook
目录 python绘图常见bug matplotlib包加载 解决中文绘图乱码解决方法 解决python中用matplotlib画多幅图时出现图形部分重叠的问题 python绘图常见bug matpl ...
- smarty文章字符截取
{%$data.dealer_info.address|replace:' ':''|cutstr:58%} cutstr:58
- C++-POJ3233-Matrix Power Series[矩阵乘法][快速幂]
构造矩阵 #include <cstdio> ; struct Matrix{int a[MAXN][MAXN];}O,I;int N; ;i<MAXN;i++);j<MAXN ...
- 栈和队列----最大值减去最小值小于等于num的子数组的数量
最大值减去最小值小于等于num的子数组的数量 给定数组arr和整数 num,共返回有多少个数组满足下列情况: max(arr[i..j])-min(arr[i..j])<=num.其中max(a ...
- centos7重启Mysql命令
执行命令/etc/init.d/mysql restart重启Mysql服务器