[bzoj3343]教主的魔法——分块
Brief description
给定一个数列,您需要支持一下两种操作:
- 给[l,r]同加一个数
- 询问[l,r]中有多少数字大于或等于v
Algorithm analyse
这个题一时想不到什么有效的数据结构,但是暴力法非常好想:一个\(\Theta(n)\)的暴力算法。
我们考虑分块做,不那么暴力。
把数据分为\(\sqrt n\)一份,那么对于每一个查询,我们都可以把这个查询分为\(\sqrt n\)个区间,修改的时候也是\(\Theta(\sqrt n)\)的级别,所以总的复杂度就是\(\Theta(\sqrt nlog\sqrt n)\)
具体地,对于每一块,我们都存储排序前和排序后的序列,这样我们就解决了这个题。
对于size的大小,我解了一个方程,跑到了2052ms,bzoj17名,已经是这个解法(不使用平衡树)的极限了,还是非常满意。

顺便%%%强校XMYZ
Code
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
int n, q, m, block;
const int maxn = 1000001;
int a[maxn], b[maxn], pos[maxn], add[maxn];
using std::sort;
using std::min;
inline int read() {
int x = 0, f = 1;
char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-')
f = -1;
ch = getchar();
}
while (isdigit(ch)) {
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
inline void reset(int x) {
int l = (x - 1) * block + 1, r = min(x * block, n);
for (int i = l; i <= r; i++)
b[i] = a[i];
sort(b + l, b + r + 1);
}
inline int find(int x, int v) {
int l = (x - 1) * block + 1, r = min(x * block, n);
int last = r;
while (l <= r) {
int mid = (l + r) >> 1;
if (b[mid] < v)
l = mid + 1;
else
r = mid - 1;
}
return last - l + 1;
}
inline void update(int x, int y, int v) {
if (pos[x] == pos[y]) {
for (int i = x; i <= y; i++)
a[i] = a[i] + v;
} else {
for (int i = x; i <= pos[x] * block; i++)
a[i] = a[i] + v;
for (int i = (pos[y] - 1) * block + 1; i <= y; i++)
a[i] = a[i] + v;
}
reset(pos[x]);
reset(pos[y]);
for (int i = pos[x] + 1; i < pos[y]; i++)
add[i] += v;
}
inline int query(int x, int y, int v) {
int sum = 0;
if (pos[x] == pos[y]) {
for (int i = x; i <= y; i++)
if (a[i] + add[pos[i]] >= v)
sum++;
} else {
for (int i = x; i <= pos[x] * block; i++)
if (a[i] + add[pos[i]] >= v)
sum++;
for (int i = (pos[y] - 1) * block + 1; i <= y; i++)
if (a[i] + add[pos[i]] >= v)
sum++;
for (int i = pos[x] + 1; i < pos[y]; i++)
sum += find(i, v - add[i]);
}
return sum;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("input", "r", stdin);
#endif
n = read(), q = read();
if (n >= 500000)
block = 3676;
else if (n >= 5000) {
block = 209;
} else
block = int(sqrt(n));
for (int i = 1; i <= n; i++) {
a[i] = read();
pos[i] = (i - 1) / block + 1;
b[i] = a[i];
}
if (n % block)
m = n / block + 1;
else
m = n / block;
for (int i = 1; i <= m; i++)
reset(i);
for (int i = 1; i <= q; i++) {
char ch[5];
int x, y, v;
scanf("%s", ch);
x = read(), y = read(), v = read();
if (ch[0] == 'M')
update(x, y, v);
else
printf("%d\n", query(x, y, v));
}
}
[bzoj3343]教主的魔法——分块的更多相关文章
- BZOJ3343: 教主的魔法 分块
2016-05-28 10:27:19 题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3343 比较显然的分块题,分块后块内排序,维护整块的附 ...
- BZOJ-3343教主的魔法+分块(大块排序二分)
传送门:https://www.luogu.org/problemnew/show/P2801 参考:http://hzwer.com/2784.html 感觉思路无比清晰:) ps:我在洛谷A的, ...
- bzoj3343: 教主的魔法 分块 标记
修改:两边暴力重构,中间打标记.复杂度:O(n0.5) 查询:中间二分两边暴力.O(n0.5logn0.5) 总时间复杂度O(n*n0.5logn0.5) 空间复杂度是n级别的 标记不用下传因为标记不 ...
- [BZOJ3343]教主的魔法
[BZOJ3343]教主的魔法 试题描述 教主最近学会了一种神奇的魔法,能够使人长高.于是他准备演示给XMYZ信息组每个英雄看.于是N个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为1.2.… ...
- Luogu 2801 教主的魔法 | 分块模板题
Luogu 2801 教主的魔法 | 分块模板题 我犯的错误: 有一处l打成了1,还看不出来-- 缩小块大小De完bug后忘了把块大小改回去就提交--还以为自己一定能A了-- #include < ...
- BZOJ 3343: 教主的魔法(分块+二分查找)
BZOJ 3343: 教主的魔法(分块+二分查找) 3343: 教主的魔法 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1172 Solved: ...
- 【BZOJ-3343】教主的魔法 分块
3343: 教主的魔法 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 950 Solved: 414[Submit][Status][Discuss ...
- 【BZOJ3343】教主的魔法 分块+二分
Description 教主最近学会了一种神奇的魔法,能够使人长高.于是他准备演示给XMYZ信息组每个英雄看.于是N个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为1.2.…….N. 每个人的 ...
- 【bzoj3343】教主的魔法 分块
[bzoj3343]教主的魔法 2014年4月26日8092 Description 教主最近学会了一种神奇的魔法,能够使人长高.于是他准备演示给XMYZ信息组每个英雄看.于是N个英雄们又一次聚集在了 ...
随机推荐
- springmvc常用jar包
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans ...
- springmvc基础篇—修改默认的配置文件名称及位置
springmvc的默认配置文件是放在WEB-INF下的,叫action-servlet.xml.根据咱们编程的习惯,一般都将配置文件放到src的根目录下,那么如何将这个文件迁移过来呢?其实很简单,请 ...
- Git 使用 粗糙记录
版本控制应该是每一个开发人员应该会的东西,奈何,学校没有学习,随着写代码的时间的加长,越来月觉得版本控制的必要性了. 记得在实习的公司,同一痛的都是SVN. 至于GIt和SVN的区别,直接看连接 ht ...
- python QQ邮箱自动发送邮件
于初学者来讲在写发送邮件代码时常见的错误有SMTPAuthenticationError535,有点懵逼,检查用户名,密码正确就是报错, 想当年笔者也是这么过来的,现在就给大家分享一下个人经验: 一, ...
- 1098 Insertion or Heap Sort (25 分)(堆)
这里的第二序列相当于是排序还没拍好的序列 对于第二个样例的第二个序列其实已经是大顶堆了 然后才进行的堆排序 知道这个就好做了 #include<bits/stdc++.h> using n ...
- Docker 安装Neo4j
拉取最新的neo4j镜像 docker pull neo4j 运行Neo4j 容器 docker run -it -d -p 7474:7474 -p 7687:7687 neo4j:latest 打 ...
- win10激活方法-专业版
该教程操作思路,Win10家庭版升为专业版,然后激活版本 首先,进入设置→关于看到如下页面: 接着,进入实操阶段: 第一步 在激活版面输入密匙 ( 把家庭版升级为专业版 ) DR9VN-GF3 ...
- Java实现网页截屏功能(基于phantomJs)
公司最近有个需求:把用户第一次的测量身体信息和最近一次测量信息进行对比,并且需要把对比的数据截成图片可以发给用户(需要在不打开网页的情况下实时对网页进行截图然后保存到服务器上,返回图片地址),通过网上 ...
- STL中mem_fun与mem_fun_ref的区别[转]
http://www.cnblogs.com/Purple_Xiapei/archive/2012/05/27/2520483.html STL中mem_fun和mem_fun_ref的用法 分类: ...
- lnmp1.4,400,500,错误
Thinkphp5或其他主流框架,入口文件未放在根目录下,比如Thinkphp5 入口文件放在/public/index.php vhost需要指向/public目录 一键安装包通常会报 open_b ...