题目描述

给出一个长为 nnn 的数列,以及 nnn 个操作,操作涉及区间加法,询问区间内小于某个值 xxx 的元素个数。

输入格式

第一行输入一个数字 nnn。

第二行输入 nnn 个数字,第 iii 个数字为 aia_ia​i​​,以空格隔开。

接下来输入 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^2c​2​​ 的数字的个数。

输出格式

对于每次询问,输出一行一个数字表示答案。

样例

样例输入

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,−2​31​​≤others、ans≤231−1 \mathrm{ans} \leq 2^{31}-1 ans≤2​31​​−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相关推荐

  1. 题解——loj6278 数列分块入门2 (分块)

    查询小于k的值 注意lower_bound一定要减去查找的起始位置得到正确的位置 调了快两天 淦 #include <cstdio> #include <algorithm> ...

  2. 数列分块入门(套题)(loj6277,loj6278,loj6279,loj6280,loj6281,loj6282,loj6283,loj6284,loj6285)

    前言 zjoi考差了,码一些分块题缓解一下心情 壹 数列分块入门 1[loj6277] 题目大意:区间加,单点查 直接分块,区间加时完全覆盖的块打tag,边界块暴力重构 块大小设为n\sqrt nn​ ...

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

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

  4. LOJ 数列分块入门6

    LOJ 数列分块入门6 题目: 题目 题解: 我都不懂这题为什么要用分块... ... 直接vector就好了... 但是如果有区间修改的话就不行了.所以这题是启示我们也可以动态分块.具体就是每次插入 ...

  5. LOJ #6280. 数列分块入门 4-分块(区间加法、区间求和)

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

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

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

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

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

  8. 「分块系列」数列分块入门3 解题报告

    数列分块入门3 题意概括 区间加法,区间求前驱. 写在前面 这题的方法与分块2方法极其类似,建议自行解决. 正题 和上一题类似,但是二分不是用来计数的,而是用来求小于c的最大值的.然后对于不完整快,将 ...

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

    题目链接:https://loj.ac/problem/6277 学习博客:http://hzwer.com/8053.html #6277. 数列分块入门 1 内存限制:256 MiB时间限制:10 ...

最新文章

  1. 新手引导动画的4种实现方式
  2. matlab中特殊符号如希腊字符
  3. 10.29 工作笔记 ndk编译C++,提示找不到头文件(ndk-build error: string: No such file or directory)...
  4. CSS的常用属性(二)
  5. 时间序列异常检测机制的研究
  6. 浅谈数学中的化归原则
  7. vs2013创建c++控制台应用程序
  8. APACHE服务器出现No input file specified.解决方案
  9. 为何python不好找工作-为什么我不建议你通过 Python 去找工作?
  10. 何冲(为奥运冠军名字作诗)
  11. 昨晚学妹参加了B站秋招笔试,还想考考我?
  12. 钝化 会钝化 订单审批流程 码一会er
  13. 程序员的数学 3 线性代数pdf
  14. “几何深度学习”受爱因斯坦启示:让AI摆脱平面看到更高的维度!
  15. 对voc2007数据集进行person的单类数据抽取
  16. C语言辅助学习系统(asp.net开发)
  17. SQL使用(一)-----联合查询
  18. 生物什么时候学公式计算机,高考生物重要规律性关系及公式精华归纳,转走吧...
  19. 用c语言把图像转成jpg格式,图像格式转换之BMP格式转换为JPG格式(示例代码)
  20. Ubuntu18.04 Ceres Solver

热门文章

  1. jQuery包裹节点用法完整示例
  2. 【自爆系列】如何从整体上削弱一支队伍的技术水平
  3. 让我们一起Go(二)
  4. es6 字符串模板 随手记
  5. 力扣 删除链表的倒数第N个节点
  6. 为什么现在又流行服务端渲染html?
  7. 贷款太多怎么缓解压力?
  8. 如果现在单位让你内退,拿基本工资,不用上班,你是否愿意?
  9. TrueNAS CORE是什么
  10. 佳能EOS R5逼出性能怪兽索尼A1,2021佳能如何接招?