LibreOJ6279. 数列分块入门 3 题解
题目链接:https://loj.ac/problem/6279
题目描述
给出一个长为 \(n\) 的数列,以及 \(n\) 个操作,操作涉及区间加法,询问区间内小于某个值 \(x\) 的前驱(比其小的最大元素)。
输入格式
第一行输入一个数字 \(n\)。
第二行输入 \(n\) 个数字,第 \(i\) 个数字为 \(a_i\),以空格隔开。
接下来输入 \(n\) 行询问,每行输入四个数字 \(opt\)、\(l\)、\(r\)、\(c\),以空格隔开。
若 \(opt=0\),表示将位于\([l,r]\) 之间的数字都加 \(c\)。
若 \(opt=1\),表示询问 \([l,r]\) 中 \(c\) 的前驱的值(不存在则输出 \(-1\))。
输出格式
对于每次询问,输出一行一个数字表示答案。
样例输入
4
1 2 2 3
0 1 3 1
1 1 4 4
0 1 2 2
1 1 2 4
样例输出
3
-1
数据范围与提示
对于 \(100%\) 的数据,\(1 \le n \le 100000, -2^{31} \le others,ans \le 2^{31}-1\)。
解题思路
本题和《数列分块入门 2》思路类似,同样是开一个数组 \(b\) 并块内排序,同样是二分找 \(\le c\) 的最大值。
实现代码如下:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 100010;
int n, m, a[maxn], b[maxn], p[maxn], v[400], op, l, r, c;
inline void chk_max(int &a, int b) {
if (b == -1) return;
if (a == -1 || a < b) a = b;
}
void update_part(int pid) {
int i1 = (pid-1)*m+1, i2 = min(pid*m+1, n+1); // 注意边界条件
for (int i = i1; i < i2; i ++)
b[i] = a[i];
sort(b+i1, b+i2);
}
void add(int l, int r, int c) {
if (p[l] == p[r]) { // 说明在同一个分块,直接更新
for (int i = l; i <= r; i ++) a[i] += c;
update_part(p[l]);
return;
}
if (l % m != 1) { // 说明l不是分块p[l]的第一个元素
for (int i = l; p[i]==p[l]; i ++) {
a[i] += c;
}
update_part(p[l]);
}
else v[p[l]] += c;
if (r % m != 0) { // 说明r不是分块p[r]的最后一个元素
for (int i = r; p[i]==p[r]; i --)
a[i] += c;
update_part(p[r]);
}
else v[p[r]] += c;
for (int i = p[l]+1; i < p[r]; i ++)
v[i] += c;
}
int pre_part(int pid, int c) {
int i1 = (pid-1)*m+1, i2 = min(pid*m+1, n+1);
int id = lower_bound(b+i1, b+i2, c-v[pid]) - (b+i1);
if (id == 0) return -1;
return b[i1+id-1]+v[pid];
}
int get_pre(int l, int r, int c) {
int res = -1;
if (p[l] == p[r]) { // 说明在同一个分块,直接更新
for (int i = l; i <= r; i ++)
if (a[i]+v[p[i]] < c)
chk_max(res, a[i]+v[p[i]]);
return res;
}
if (l % m != 1) { // 说明l不是分块p[l]的第一个元素
for (int i = l; p[i]==p[l]; i ++)
if (a[i]+v[p[i]] < c)
chk_max(res, a[i]+v[p[i]]);
}
else chk_max(res, pre_part(p[l], c));
if (r % m != 0) { // 说明r不是分块p[r]的最后一个元素
for (int i = r; p[i]==p[r]; i --)
if (a[i]+v[p[i]] < c)
chk_max(res, a[i]+v[p[i]]);
}
else chk_max(res, pre_part(p[r], c));
for (int i = p[l]+1; i < p[r]; i ++)
chk_max(res, pre_part(i, c));
return res;
}
int main() {
scanf("%d", &n);
m = sqrt(n);
for (int i = 1; i <= n; i ++) p[i] = (i-1)/m + 1;
for (int i = 1; i <= n; i ++) scanf("%d", &a[i]);
for (int i = 1; i <= n; i += m) update_part(p[i]); // 初始化
for (int i = 0; i < n; i ++) {
scanf("%d%d%d%d", &op, &l, &r, &c);
if (op == 0) add(l, r, c);
else printf("%d\n", get_pre(l, r, c));
}
return 0;
}
LibreOJ6279. 数列分块入门 3 题解的更多相关文章
- LibreOJ 6277. 数列分块入门 1 题解
题目链接:https://loj.ac/problem/6277 题目描述 给出一个长为 \(n\) 的数列,以及 \(n\) 个操作,操作涉及区间加法,单点查值. 输入格式 第一行输入一个数字 \( ...
- LibreOJ 6278. 数列分块入门 2 题解
题目链接:https://loj.ac/problem/6278 题目描述 给出一个长为 \(n\) 的数列,以及 \(n\) 个操作,操作涉及区间加法,询问区间内小于某个值 \(x\) 的元素个数. ...
- LOJ6277~6285 数列分块入门
Portals 分块需注意的问题 数组大小应为,因为最后一个块可能会超出的范围. 当操作的区间在一个块内时,要特判成暴力修改. 要清楚什么时候应该+tag[t] 数列分块入门 1 给出一个长为的数列, ...
- 数列分块入门九题(三):LOJ6283~6285
Preface 最后一题我一直觉得用莫队是最好的. 数列分块入门 7--区间乘法,区间加法,单点询问 还是很简单的吧,比起数列分块入门 7就多了个区间乘. 类似于线段树,由于乘法的优先级高于加法,因此 ...
- 数列分块入门九题(二):LOJ6280~6282
Preface 个人感觉这中间的三题是最水的没有之一 数列分块入门 4--区间加法,区间求和 这个也是很多数据结构完爆的题目线段树入门题,但是练分块我们就要写吗 修改还是与之前类似,只不过我们要维护每 ...
- 数列分块入门九题(一):LOJ6277~6279
Preface 分块,一个神奇的暴力算法.可以把很多\(O(n^2)\)的数据结构题的暴力优化到常数极小的\(O(n\sqrt n)\).当一些毒瘤题无法用线段树,主席树,平衡树,树状数组...... ...
- LOJ6285 数列分块入门9(分块)
昨天对着代码看了一晚上 然后今天终于在loj上过了 数列分块入门9题撒花★,°:.☆( ̄▽ ̄)/$:.°★ . 然后相当玄学 块的大小调成\(\sqrt{n}\)会TLE,改成150就过了 啧 然后就 ...
- LOJ 6277:数列分块入门 1(分块入门)
#6277. 数列分块入门 1 内存限制:256 MiB时间限制:100 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: hzwer 提交提交记录统计讨论 3 测试数据 题目描述 给出一 ...
- LOJ #6285. 数列分块入门 9-分块(查询区间的最小众数)
#6285. 数列分块入门 9 内存限制:256 MiB时间限制:1500 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: hzwer 提交提交记录统计测试数据讨论 2 题目描述 给 ...
随机推荐
- 解决 vs 出现Error MC3000 给定编码中的字符无效
在 xaml 写中文注释,发现编译失败 Error MC3000 给定编码中的字符无效 我的 xaml 写了一句代码 <Grid> <!--林德熙--> </Grid&g ...
- TAE words
love handle pang carbohydrate podiatry splay out Cinderella liposuction mingle fly t ...
- tp3.2.3 解决http://lx.com/后必须加index.php才能访问的问题,配置文件中忘了加index index.php index.html 等默认文件
server { listen 80; server_name lx.com; root "D:\phpstudy\PHPTutorial\WWW\liuxue"; locatio ...
- xml path 列转行实例
SQL Server2005提供了一个新查询语法——For XML PATH(''),这个语法有什么用呢?想象一下这样一个查询需求:有两个表,班级表A.学生表B,要查询一个班级里有哪些学生?针对这个需 ...
- xshell评估期已过怎么办
重新下载更新即可,不要看到英文一脸懵逼,直接在页面中有红色*号的地方输入个人信息,licensetype 必须选 Home and School use(家庭和个人使用),最主要的是输入邮箱(必须是个 ...
- 第三次脱发——Scurm学(ctrl)习(C)心得
Scrum 学习心得: 首先,敏捷并不是一门具体的技术,而是一种理念或者说是一种思想.它可以指导我们更加高效的开发. 其次,敏捷开发都具有以下共同的特征: 迭代式开发 增量交付 开发团队和用户反馈推动 ...
- HTML--表格与表单
一.表格 <table></table>表格 width:宽度.可以用像素或百分比表示. 常用960像素. border:边框,常用值为0. cellpadding:内容跟边框 ...
- poj 3295
题目意思就是计算表达式的值,如果所有情况下表达式为真就输出“tautology”,否则输出“not”. p, q, r, s, and t,每个人有两种情况,综合起来一共有32种情况,枚举所有情况最后 ...
- Spring Cloud探路(一) Erueka服务器的建立
组件名:Netflix Eureka 作用:支撑微服务的自注册.自发现,提供负载均衡能力 开发环境使用IDEA 1.新建Eureka Server,新建maven项目,配置pom.xml <p ...
- 2019.12.15 QLU and SNDU期末联赛
题目列表: 1582.柳予欣的舔狗行为 1587.柳予欣的女朋友们在分享水果 1585.柳予欣和她女朋友的购物计划 1579.FFFFFunctions 1588.Zeckendorf 1586.柳予 ...