[LOJ6278]数列分块入门 2
题目描述
给出一个长为 nnn 的数列,以及 nnn 个操作,操作涉及区间加法,询问区间内小于某个值 xxx 的元素个数。
输入格式
第一行输入一个数字 nnn。
第二行输入 nnn 个数字,第 iii 个数字为 aia_iai,以空格隔开。
接下来输入 nnn 行询问,每行输入四个数字 opt\mathrm{opt}opt、lll、rrr、ccc,以空格隔开。
若 opt=0\mathrm{opt} = 0opt=0,表示将位于 [l,r][l, r][l,r] 的之间的数字都加 ccc。
若 opt=1\mathrm{opt} = 1opt=1,表示询问 [l,r][l, r][l,r] 中,小于 c2c^2c2 的数字的个数。
输出格式
对于每次询问,输出一行一个数字表示答案。
样例
样例输入
4
1 2 2 3
0 1 3 1
1 1 3 2
1 1 4 1
1 2 3 2
样例输出
3
0
2
数据范围与提示
对于 100% 100\% 100% 的数据,1≤n≤50000,−231≤others 1 \leq n \leq 50000, -2^{31} \leq \mathrm{others}1≤n≤50000,−231≤others、ans≤231−1 \mathrm{ans} \leq 2^{31}-1 ans≤231−1。
这道水题调了我接近50分钟,不开心。
一开始以为没开longlong,实际上没有仔细读题,我还以为是求区间中小于等于$c^2$的个数呢...然后就因为没仔细读题贡献了接近一页的wa。
这题分块做,对于每个块,在块内进行排序,为了方便用vector存储就行了,然后修改的时候,整块直接打标记,零散的块整个暴力重构,查询整块在vector内二分,零散的暴力。
反正题的数据范围也不强,这个水题随便写写就能过。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <vector> #include <queue> using namespace std; #define reg register #define int long long inline int read() {int res = 0;char ch=getchar();bool fu=0;while(!isdigit(ch))fu|=(ch=='-'),ch=getchar();while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48),ch=getchar();return fu?-res:res; } int Bl = 500; #define N 50005 int n; int a[N]; int belong[N]; int L[5005], R[5005], tag[5005]; vector <int> ve[5005];signed main() {n = read();for (reg int i = 1 ; i <= n ; i ++) a[i] = read();Bl = sqrt(n);for (reg int i = 1 ; i <= n ; i ++){belong[i] = (i - 1) / Bl + 1;if (!L[belong[i]]) L[belong[i]] = i, R[belong[i]-1] = i - 1;}R[belong[n]] = n;for (reg int i = 1 ; i <= n ; i ++)ve[belong[i]].push_back(a[i]);for (reg int i = 1 ; i <= belong[n] ; i ++) sort(ve[i].begin(), ve[i].end());int Q = n;while(Q--){int opt = read(), l = read(), r = read(), c = read();if (opt == 0) {if (belong[l] == belong[r]) {ve[belong[l]].clear();for (reg int i = l ; i <= r ; i ++) a[i] += c;for (reg int i = L[belong[l]] ; i <= R[belong[l]] ; i ++)ve[belong[i]].push_back(a[i]);sort(ve[belong[l]].begin(), ve[belong[l]].end());} else if (belong[l] + 1 == belong[r]) {ve[belong[l]].clear();for (reg int i = l ; i <= R[belong[l]] ; i ++) a[i] += c;for (reg int i = L[belong[l]] ; i <= R[belong[l]] ; i ++)ve[belong[i]].push_back(a[i]);sort(ve[belong[l]].begin(), ve[belong[l]].end());ve[belong[r]].clear();for (reg int i = L[belong[r]] ; i <= r ; i ++) a[i] += c;for (reg int i = L[belong[r]] ; i <= R[belong[r]] ; i ++)ve[belong[i]].push_back(a[i]);sort(ve[belong[r]].begin(), ve[belong[r]].end());} else {for (reg int i = belong[l] + 1 ; i <= belong[r] - 1 ; i ++) tag[i] += c;ve[belong[l]].clear();for (reg int i = l ; i <= R[belong[l]] ; i ++) a[i] += c;for (reg int i = L[belong[l]] ; i <= R[belong[l]] ; i ++)ve[belong[i]].push_back(a[i]);sort(ve[belong[l]].begin(), ve[belong[l]].end());ve[belong[r]].clear();for (reg int i = L[belong[r]] ; i <= r ; i ++) a[i] += c;for (reg int i = L[belong[r]] ; i <= R[belong[r]] ; i ++)ve[belong[i]].push_back(a[i]);sort(ve[belong[r]].begin(), ve[belong[r]].end());}} else {c *= c;int ans = 0;if (belong[l] == belong[r]) {for (reg int i = l ; i <= r ; i ++) if (a[i] + tag[belong[i]] < c) ans++;printf("%lld\n", ans);} else if (belong[l] + 1 == belong[r]) {for (reg int i = l ; i <= r ; i ++) if (a[i] + tag[belong[i]] < c) ans++;printf("%lld\n", ans);} else {for (reg int i = l ; i <= R[belong[l]] ; i ++) if (a[i] + tag[belong[i]] < c) ans++;for (reg int i = L[belong[r]] ; i <= r ; i ++) if (a[i] + tag[belong[i]] < c) ans++;for (reg int i = belong[l] + 1 ; i <= belong[r] - 1 ; i ++)ans += lower_bound(ve[i].begin(), ve[i].end(), c - tag[i]) - ve[i].begin();printf("%lld\n", ans);}}}return 0; }
转载于:https://www.cnblogs.com/BriMon/p/9859307.html
[LOJ6278]数列分块入门 2相关推荐
- 题解——loj6278 数列分块入门2 (分块)
查询小于k的值 注意lower_bound一定要减去查找的起始位置得到正确的位置 调了快两天 淦 #include <cstdio> #include <algorithm> ...
- 数列分块入门(套题)(loj6277,loj6278,loj6279,loj6280,loj6281,loj6282,loj6283,loj6284,loj6285)
前言 zjoi考差了,码一些分块题缓解一下心情 壹 数列分块入门 1[loj6277] 题目大意:区间加,单点查 直接分块,区间加时完全覆盖的块打tag,边界块暴力重构 块大小设为n\sqrt nn ...
- #6279. 数列分块入门 3(区间修改,查询权值前驱)
#6279. 数列分块入门 3 这是使用hzwer建议的set写的分块代码,set自动排序,支持二分查找,但是常数较大,比我下面写的用vector实现的分块慢了三倍,空间大了10倍. #include ...
- LOJ 数列分块入门6
LOJ 数列分块入门6 题目: 题目 题解: 我都不懂这题为什么要用分块... ... 直接vector就好了... 但是如果有区间修改的话就不行了.所以这题是启示我们也可以动态分块.具体就是每次插入 ...
- LOJ #6280. 数列分块入门 4-分块(区间加法、区间求和)
#6280. 数列分块入门 4 内存限制:256 MiB时间限制:500 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: hzwer 提交提交记录统计测试数据讨论 题目描述 给出一个长为 ...
- 数列分块入门 (1 ~ 7)
分块 6277. 数列分块入门 1 分块思想 我们把每m个元素分成一块,所以我们总共的块数就是n/mn / mn/m块,一般情况下我们取m=nm = \sqrt{n}m=n.对于区间加操作,我们可以 ...
- 「分块」数列分块入门1 – 9
ACM模板 放暑假了,回归!!! 自己不会写暴力,而且好久没写代码了,于是学学分块的优雅暴力~ 「分块入门-LibreOJ」 「分块」数列分块入门1 – 9 by hzwer 数列简单分块问题实际上有 ...
- 「分块系列」数列分块入门3 解题报告
数列分块入门3 题意概括 区间加法,区间求前驱. 写在前面 这题的方法与分块2方法极其类似,建议自行解决. 正题 和上一题类似,但是二分不是用来计数的,而是用来求小于c的最大值的.然后对于不完整快,将 ...
- #6277. 数列分块入门 1
题目链接:https://loj.ac/problem/6277 学习博客:http://hzwer.com/8053.html #6277. 数列分块入门 1 内存限制:256 MiB时间限制:10 ...
最新文章
- 新手引导动画的4种实现方式
- matlab中特殊符号如希腊字符
- 10.29 工作笔记 ndk编译C++,提示找不到头文件(ndk-build error: string: No such file or directory)...
- CSS的常用属性(二)
- 时间序列异常检测机制的研究
- 浅谈数学中的化归原则
- vs2013创建c++控制台应用程序
- APACHE服务器出现No input file specified.解决方案
- 为何python不好找工作-为什么我不建议你通过 Python 去找工作?
- 何冲(为奥运冠军名字作诗)
- 昨晚学妹参加了B站秋招笔试,还想考考我?
- 钝化 会钝化 订单审批流程 码一会er
- 程序员的数学 3 线性代数pdf
- “几何深度学习”受爱因斯坦启示:让AI摆脱平面看到更高的维度!
- 对voc2007数据集进行person的单类数据抽取
- C语言辅助学习系统(asp.net开发)
- SQL使用(一)-----联合查询
- 生物什么时候学公式计算机,高考生物重要规律性关系及公式精华归纳,转走吧...
- 用c语言把图像转成jpg格式,图像格式转换之BMP格式转换为JPG格式(示例代码)
- Ubuntu18.04 Ceres Solver