#6279. 数列分块入门 3



这是使用hzwer建议的set写的分块代码,set自动排序,支持二分查找,但是常数较大,比我下面写的用vector实现的分块慢了三倍,空间大了10倍。

#include <cstdio>
#include <cstring>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
#include <set>
using namespace std;
typedef int ll;const int N = 500007, M = 500007, INF = 0x3f3f3f3f;ll read() {ll x = 0, f = 1;char ch = getchar();while (ch < '0' || ch > '9') {if (ch == '-')f = -1;ch = getchar();}while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0';ch = getchar();}return x * f;
}//就是要避免重复的权值的,所以用setint n, m;
int v[N];
int block, bi[N];
int add_tag[N];
set<int>st[N];void modify(int a, int b, int c)
{for(int i = a; i <= min(bi[a] * block, b); ++ i){st[bi[a]].erase(v[i]);v[i] += c;st[bi[a]].insert(v[i]);}if(bi[a] != bi[b]){for(int i = (bi[b] - 1) * block + 1; i <= b; ++ i){st[bi[b]].erase(v[i]);v[i] += c;st[bi[b]].insert(v[i]);}}for(int i = bi[a] + 1; i <= bi[b] - 1; ++ i){add_tag[i] += c;}
}int query(int a, int b, int c)
{int ans = -1;for(int i = a; i <= min(bi[a] * block, b); ++ i){int val = v[i] + add_tag[bi[a]];if(val < c)ans = max(ans, val);}if(bi[a] != bi[b]){for(int i = (bi[b] - 1) * block + 1; i <= b; ++ i){int val = v[i] + add_tag[bi[b]];if(val < c)ans = max(ans, val);}}for(int i = bi[a] + 1; i <= bi[b] - 1; ++ i){int val = c - add_tag[i];set<int> :: iterator it = st[i].lower_bound(val);if(it == st[i].begin())continue;-- it;ans = max(ans, *it + add_tag[i]);}return ans;
}int main()
{n = read();block = sqrt(n);for(int i = 1; i <= n; ++ i)v[i] = read();for(int i = 1; i <= n; ++ i){bi[i] = (i - 1) / block + 1;st[bi[i]].insert(v[i]);}//cout << "ok" << endl;for(int i = 1; i <= n; ++i){int op = read(), a = read(), b = read(), c = read();if(op == 0){modify(a, b, c);}else if(op == 1){printf("%d\n", query(a, b, c));}}return 0;
}

vector实现的代码:

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
#define x first
#define y second
#define debug(x) cout << x << "ok" << endl
using namespace std;
typedef long long ll;
//typedef __int128 int;oj上可用,编译器上不可用
const int N = 200007, M = 507, INF = 0x3f3f3f3f;
const double eps = 1e-8;
typedef pair<int, int>PII;int n, m;
int a[N];
int block, cnt;
vector<int>vc[M];
int belong[N];
int add_lz[M];void pre()//块间无序,块内有序
{for(int i = 1; i <= cnt; ++ i)sort(vc[i].begin(), vc[i].end());
}void update(int block_num)//sqrt(n)
{vc[block_num].clear();//上一个块的个数+1到这个块的个数——遍历该块的所有元素for(int i = (block_num - 1) * block + 1; i <= block_num * block; ++ i)vc[block_num].push_back(a[i]);sort(vc[block_num].begin(), vc[block_num].end());
}void modify(int l, int r, int k)
{//先处理 l 块for(int i = l; i <= min(belong[l] * block, r); ++ i){a[i] += k;}update(belong[l]);if(belong[l] != belong[r]){//不是同一个块,处理 r 块for(int i = (belong[r] - 1) * block + 1; i <= r; ++ i){a[i] += k;//先只遍历r所属的块,中间的打标记}update(belong[r]);}for(int i = belong[l] + 1; i < belong[r]; ++ i){add_lz[i] += k;}
}int query(int l, int r, int maxv)//找小于maxv的最大数(前驱)
{int ans = -INF;for(int i = l; i <= min(belong[l] * block, r); ++ i){if(a[i] + add_lz[belong[i]] < maxv){ans = max(ans, a[i] + add_lz[belong[i]]);}}if(belong[l] != belong[r]){for(int i = (belong[r] - 1) * block + 1; i <= r; ++ i){if(a[i] + add_lz[belong[i]] < maxv){ans = max(ans, a[i] + add_lz[belong[i]]);}}}for(int i = belong[l] + 1; i < belong[r]; ++ i){if(vc[i].at(0) + add_lz[i] >= maxv)//块内最小值+懒惰标记都已经大于maxv那就没有继续的必要continue;int k = lower_bound(vc[i].begin(), vc[i].end(), maxv - add_lz[i]) - vc[i].begin();ans = max(ans, vc[i].at(k - 1) + add_lz[i]);}return ans;
}int main()
{scanf("%d", &n);block = sqrt(n);//每个块的个数for(int i = 1; i <= n; ++ i){scanf("%d", &a[i]);belong[i] = (i - 1) / block + 1;//从1开始,求当前是第几块vc[belong[i]].push_back(a[i]);if(i % block == 1)//注意有头块和尾块,因为n不一定是完全平方数cnt ++ ;}pre();//排序预处理for(int i = 1; i <= n; ++ i){int op, l, r, c;scanf("%d%d%d%d", &op, &l, &r, &c);if(op == 0){modify(l, r, c);}else {int res = query(l, r, c);//找前驱if(res == -INF){puts("-1");continue;}printf("%d\n", res);}}return 0;
}

#6279. 数列分块入门 3(区间修改,查询权值前驱)相关推荐

  1. LOJ #6279. 数列分块入门 3-分块(区间加法、查询区间内小于某个值x的前驱(比其小的最大元素))...

    #6279. 数列分块入门 3 内存限制:256 MiB时间限制:1500 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: hzwer 提交提交记录统计测试数据讨论 3 题目描述 给出一 ...

  2. #6279. 数列分块入门 3

    数列分块入门 3 #include<bits/stdc++.h> using namespace std; #define ll long long const int N=1000010 ...

  3. LibreOJ 6279 数列分块入门 3(分块+排序)

    题解:自然是先分一波块,把同一个块中的所有数字压到一个vector中,将每一个vector进行排序.然后对于每一次区间加,不完整的块加好后暴力重构,完整的块直接修改标记.查询时不完整的块暴力找最接近x ...

  4. LibreOj 6279数列分块入门 3 练习了一下set

    题目链接:https://loj.ac/problem/6279 推荐博客:https://blog.csdn.net/qq_36038511/article/details/79725027 这题区 ...

  5. 数列分块入门4(区间求和)

    原题:https://loj.ac/problem/6280 题解:这题不太难,分块求区间和就行了. #include<bits/stdc++.h> #define reg registe ...

  6. 数列分块入门2(区间小于c的个数)

    原题:http://www.caioj.cn/problem.php?id=1245 题解:我们可以分块处理.两边的块暴力,中间的块可以先预处理排序,再用lower_bound求出个数. #inclu ...

  7. 「分块」数列分块入门1 – 9

    ACM模板 放暑假了,回归!!! 自己不会写暴力,而且好久没写代码了,于是学学分块的优雅暴力~ 「分块入门-LibreOJ」 「分块」数列分块入门1 – 9 by hzwer 数列简单分块问题实际上有 ...

  8. 数列分块入门 (1 ~ 7)

    分块 6277. 数列分块入门 1 分块思想 我们把每m个元素分成一块,所以我们总共的块数就是n/mn / mn/m块,一般情况下我们取m=nm = \sqrt{n}m=n​.对于区间加操作,我们可以 ...

  9. LOJ——#6277. 数列分块入门 1

    ~~推荐播客~~ 「分块」数列分块入门1 – 9 by hzwer 浅谈基础根号算法--分块 博主蒟蒻,有缘人可直接观摩以上大佬的博客... #6277. 数列分块入门 1 题目大意: 给出一个长为 ...

最新文章

  1. 在Ubuntu 14.04 64bit上编译并研究State Threads网络线程库源码
  2. IPv6扩展头部 (一) 扩展头部格式、类型与扩展选项
  3. 訪问劫持?訪问苏宁时发生的怪事
  4. 剑指offer:39-42记录
  5. 数字图像恢复matlab结论,matlab模糊图像恢复数字图像处理
  6. 场景7:带有Linux网桥的提供商网络
  7. oracle把列数据串成一个字符串,一组数据,如何根据一个字段值分组后,把另一字段的字符串累加连接起来?...
  8. 阶段3 2.Spring_04.Spring的常用注解_2 常用IOC注解按照作用分类
  9. 如何修复损坏的excel文件?
  10. Linux 常用命令和快捷键
  11. DELPHI 读取TXT文件unicode乱码
  12. 汽车车载智能终端T-BOX
  13. 微信小程序实现九宫格切图,保存功能!
  14. 不动点迭代 开平方 Excel演示
  15. 如何卸载流氓软件Avast
  16. 15、【易混淆概念集】-第九章 职责分配矩阵(RAM) 活动资源估算、资源分解结构 获取资源 资源/项目/自然日历区别 虚拟团队、集中办公、认可与奖励 塔克曼阶梯理论 冲突管理 权力类型
  17. Error while bringing up minion for multi-master.
  18. 测试开发岗 - 常见面试题
  19. 程序员怒怼外包公司HR:1万块钱还想招C语言开发,简直石乐志!
  20. 消防给水及消火栓系统技术规范_消防给水及消火栓系统技术规范9、10、11 习题...

热门文章

  1. 关于双目立体视觉的三大基本算法及发展现状的总结
  2. 详解通用物体检测算法:基于锚框与无需锚框
  3. 巨大的需求之下 人工智能如何更快落地?
  4. Tomcat介绍、安装JDK、安装Tomcat
  5. 如何添加ORACLE 的 ODBC
  6. 服务器市场严酷竞争下的众生相
  7. javaEE之------Spring-----》 AspectJ注解
  8. 《C++ Primer Plus》第8章 函数探幽 学习笔记
  9. runtime 任意类型 model 数据库方便存储
  10. ExtJs grid合并单元格