# 解题思路

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

然后再说进行查询的操作,起初,我们需要在每一个块内进行排序。保证顺序时单调上升的(在每一个块内,是独立的),然后查询的时候对每一块($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. HDU6024:Building Shops(DP)

    传送门 题意 在一条直线上有n个教室,现在要设置糖果店,使得最后成本最小,满足以下两个条件: 1.若该点为糖果店,费用为cost[i]; 2.若不是,则为loc[i]-最近的糖果店的loc 分析 dp ...

  2. hdoj3714【三分】

    手动插姿势: 三分法可以应用于凸函数或者凹函数的求极值. 三分讲解:http://blog.csdn.net/pi9nc/article/details/9666627 三分模板:http://www ...

  3. python __builtins__ staticmethod类 (64)

    64.'staticmethod', 返回静态方法 class staticmethod(object) | staticmethod(function) -> method | | Conve ...

  4. python __builtins__ credits类 (15)

    15.'credits', 信用 class _Printer(builtins.object) | interactive prompt objects for printing the licen ...

  5. bzoj 2927: [Poi1999]多边形之战【博弈论】

    先手必胜状态是黑三角在边上 然后其他情况脑补一下,n为偶数先手必胜,可以理解为从某一边取,先手总有办法让后手取得一边有奇数个 #include<iostream> #include< ...

  6. bzoj 2560: 串珠子【状压dp】

    正难则反,设g[s]为集合s不一定联通的方案数,这个很好求,把边数+1乘起来即可,f[s]为s一定联通的方案数 f考虑容斥,就是g[s]-Σf[nw]*g[s^nw],nw是s的子集,这样就减掉了不联 ...

  7. 第十四篇 .NET高级技术之反射

    两个现实中的例子:1.B超:大家体检的时候大概都做过B超吧,B超可以透过肚皮探测到你内脏的生理情况.这是如何做到的呢?B超是B型超声波,它可以透过肚皮通过向你体内发射B型超声波,当超声波遇到内脏壁的时 ...

  8. Django使用dwebsocket来通信,服务器报错[Error 10038]

    记录这次Django踩得最大的一次坑,没有之一.前前后后困扰了一周. 在使用Django的dwebsocket模块建立websocket时,不管是前端主动关闭,还是页面刷新,还是页面关闭.服务端均会报 ...

  9. scanf()和scanf_s()

    在最初的C语言中,原版的输入就是scanf("<格式化字符串>",<地址表>) ANSI C中没有scanf_s(),只有scanf(),scanf()在读 ...

  10. Clone a Pluggable Database – 12c Edition

    1. 1.Tnsnames when connecting to either Container or Pluggable instance The tnsnames.ora should be c ...