# 解题思路

修改,就是一个区间修改的常规操作,但是为了迎合查询的需要,对两端的不完整的块需要暴力重构,重新进行排序操作,保证每一块都是单调上升的顺序。

然后再说进行查询的操作,起初,我们需要在每一个块内进行排序。保证顺序时单调上升的(在每一个块内,是独立的),然后查询的时候对每一块($k$)都二分查找到大于 $num + tag[k]$ 的第一个数的位置,然后就可以得到一共有多少大于 $num$ 的数了。

值得注意的是,有些题解写的是对原序列直接进行排序,这就有一个错误,那就是在排序之后序列的顺序改变,改变了之后在进行区间修改的时候就不能保证正确性了。

所以我们开一个 vector 将每个块内的数都存下来。我的代码 T 了一个点,但是了 O2 过了,懒得再去卡常了

# 附上代码

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <vector>
using namespace std;
const int maxn = 1e6+;
int N, Q, arr[maxn], in[maxn], cnt, tag[maxn];
vector<int> b[];
struct BLOCK {
template <typename T> inline void read(T &x) {
x = ; T f = ; char c = getchar();
while (c < '' || c > '') {if(c == '-') f = -; c = getchar();}
while (c <= '' && c >= '') {x = x* + c-''; c = getchar();}
x *= f;
}
void reset(int k) {
b[k].clear();
for(int i=(k-)*cnt+; i<=min(k*cnt, N); i++)
arr[i] += tag[k], b[k].push_back(arr[i]);
sort(b[k].begin(), b[k].end());
tag[k] = ;
}
void build() {
cnt = sqrt(N);
for(int i=; i<=N; i++) {
read(arr[i]);
in[i] = (i-)/cnt+;
b[in[i]].push_back(arr[i]);
}
for(int i=in[]; i<=in[N]; i++)
sort(b[i].begin(), b[i].end());
}
void update(int l, int r, int num) {
for(int i=l; i<=min(in[l]*cnt, r); i++)
arr[i] += num;
reset(in[l]);
if(in[l] != in[r]) {
for(int i=(in[r]-)*cnt+; i<=r; i++)
arr[i] += num;
reset(in[r]);
}
for(int i=in[l]+; i<in[r]; i++)
tag[i] += num;
}
int check(int k, int num) {
int ans = (b[k].end()-lower_bound(b[k].begin(), b[k].end(), num-tag[k]));
return ans;
}
int query(int l, int r, int num) {
int ans = ;
for(int i=l; i<=min(in[l]*cnt, r); i++)
if(arr[i] + tag[in[i]] >= num) ans ++;
if(in[l] != in[r]) {
for(int i=(in[r]-)*cnt+; i<=r; i++)
if(arr[i] + tag[in[i]] >= num) ans ++;
}
for(int i=in[l]+; i<in[r]; i++)
ans += check(i, num);
return ans;
}
BLOCK () {
read(N), read(Q);
build();
char opt;
int l, r, num;
for(int i=; i<=Q; i++) {
cin>>opt;
read(l), read(r), read(num);
if(opt == 'M') update(l, r, num);
else printf("%d\n", query(l, r, num));
}
}
}BLO;
int main() {}

「 Luogu P2801 」 教主的魔法——分块的更多相关文章

  1. 「BZOJ3343」教主的魔法(分块+二分查找)

    题意: 给定一个数列,您需要支持以下两种操作:给[l,r]同加一个数询问[l,r]中有多少数字大于或等于v (n<=1000000,m<=3000) 题解 块内排序二分查询修改就用个数组存 ...

  2. Luogu 2801 教主的魔法 | 分块模板题

    Luogu 2801 教主的魔法 | 分块模板题 我犯的错误: 有一处l打成了1,还看不出来-- 缩小块大小De完bug后忘了把块大小改回去就提交--还以为自己一定能A了-- #include < ...

  3. BZOJ 3343: 教主的魔法(分块+二分查找)

    BZOJ 3343: 教主的魔法(分块+二分查找) 3343: 教主的魔法 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1172  Solved:  ...

  4. 洛谷P2801 教主的魔法 [分块,二分答案]

    题目传送门 教主的魔法 题目描述 教主最近学会了一种神奇的魔法,能够使人长高.于是他准备演示给XMYZ信息组每个英雄看.于是N个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为1.2.…….N. ...

  5. 题解 P2801 【教主的魔法】

    分块入门题,不错的,建议大家做一做 开始学习 先看一下数列分块入门 2 这道题想让我们求区间[l,r]>=c的个数,然后我们可以看到"数列分块入门 2"是求区间[l,r]&l ...

  6. BZOJ 3343: 教主的魔法 [分块]【学习笔记】

    3343: 教主的魔法 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1172  Solved: 526[Submit][Status][Discus ...

  7. 【BZOJ-3343】教主的魔法 分块

    3343: 教主的魔法 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 950  Solved: 414[Submit][Status][Discuss ...

  8. 【BZOJ3343】教主的魔法 分块+二分

    Description 教主最近学会了一种神奇的魔法,能够使人长高.于是他准备演示给XMYZ信息组每个英雄看.于是N个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为1.2.…….N. 每个人的 ...

  9. BZOJ3343: 教主的魔法 分块

    2016-05-28  10:27:19 题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3343 比较显然的分块题,分块后块内排序,维护整块的附 ...

随机推荐

  1. django-ckeditor表情包修改

    一.版本 Django==1.11 django-ckeditor==5.2.2 二.关键步骤 1.删除旧的ckeditor静态文件 所在目录:项目目录下的static文件夹下的ckditor文件夹 ...

  2. 机器学习(2):简单线性回归 | 一元回归 | 损失计算 | MSE

    前文再续书接上一回,机器学习的主要目的,是根据特征进行预测.预测到的信息,叫标签. 从特征映射出标签的诸多算法中,有一个简单的算法,叫简单线性回归.本文介绍简单线性回归的概念. (1)什么是简单线性回 ...

  3. 51nod 1050【DP】

    思路: 就是先正常的dp一下求一个最大连续子串,然后特殊情况就是sum-最小连续子串.. 比一比谁大谁小就好了 #include <stdio.h> #include <string ...

  4. POJ2533/hdoj1950【DP】

    O(nlog(n))的方法: 定义d[k]:长度为k的上升子序列的最末元素,若有多个长度为k的上升子序列,则记录最小的那个最末元素. d中元素也是单调递增的. #include <iostrea ...

  5. IT兄弟连 JavaWeb教程 Servlet

    Servlet的定义 Java Servlet是运行在Web服务器或应用服务器上的程序,它是作为来自Web浏览器或其他HTTP客户端的请求和HTTP服务器上的数据库或应用程序之间的中间层. 使用Ser ...

  6. Python之单元测试——HTMLTestRunner

    前置条件:把HTMLTestRunner.py文件拷贝到External Libraries—>site-packages里面 import unittestimport HTMLTestRun ...

  7. 谷歌编码风格内容,新建一个xml文件,复制进去就可以在eclipse里面用了,命名--eclipse-java-google-style.xml

    <?xml version="1.0" encoding="UTF-8" standalone="no"?> <profi ...

  8. 131 Palindrome Partitioning 分割回文串

    给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串.返回 s 所有可能的分割方案.例如,给出 s = "aab",返回[  ["aa"," ...

  9. innobackupex的使用

    优点: 不暂停服务器创建Innodb热备份 为mysql做增量的备份 在mysql服务器之间做在线表迁移 使创建mysql replication更加容易 备份mysql但不增加服务器的负载 安装:x ...

  10. Unity坐标系统

    Unity使用了几种不同的坐标系统,分别如下: 1.屏幕坐标(Screen Space):屏幕坐标是以像素来定义的,以屏幕左下角为(0, 0)点,右上角为(Screen.width, Screen.h ...