【学习心得】分块
2016-05-20 20:37
316 查看
介绍
分块是信息学中经常用到的一个思想。主要是通过将整个序列分割成根号个块来保证复杂度。分块可以对询问进行预处理,修改或查询时,主要就是靠完整的块打标记或直接查,不完整的块暴力改或暴力查。这样每个块中的操作的复杂度不会超过sqrt(n)。对于一些复杂的树形数据结构,在考场上有可能会紧张写不出来,这时候使用分块就是一个很好的选择,此时分块的代码复杂度与分数的性价比是很高的。
(题外话:其实分块是一个非常玄学的做法,块的大小不同,时间效率也会不同,我有很多次都是sqrtT了,乘或除一个常数就AC了。。。)
参考模板
这里以bzoj3343教主的魔法为例,放上参考模板一份。#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #ifdef WIN32 #define LL "%I64d" #else #define LL "%lld" #endif #ifdef CT #define debug(...) printf(__VA_ARGS__) #define setfile() #else #define debug(...) #define filename "" #define setfile() freopen(filename".in", "r", stdin); freopen(filename".out", "w", stdout); #endif #define R register #define getc() (S == T && (T = (S = B) + fread(B, 1, 1 << 15, stdin), S == T) ? EOF : *S++) #define dmax(_a, _b) ((_a) > (_b) ? (_a) : (_b)) #define dmin(_a, _b) ((_a) < (_b) ? (_a) : (_b)) #define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0) #define cmin(_a, _b) (_a > (_b) ? _a = (_b) : 0) char B[1 << 15], *S = B, *T = B; inline int FastIn() { R char ch; R int cnt = 0; R bool minus = 0; while (ch = getc(), (ch < '0' || ch > '9') && ch != '-') ; ch == '-' ? minus = 1 : cnt = ch - '0'; while (ch = getc(), ch >= '0' && ch <= '9') cnt = cnt * 10 + ch - '0'; return minus ? -cnt : cnt; } #define maxn 1000010 #define maxsize 4010 int a[maxn], b[maxn], block, id[maxn], n, q, ans, w, tag[maxsize]; inline void build(R int x) { R int l = x * block, r = (x + 1) * block - 1; cmin(r, n); for (R int i = l; i <= r; ++i) b[i] = a[i]; std::sort(b + l, b + r + 1); } inline void voi_query(R int l, R int r) { for (R int i = l; i <= r; ++i) if (a[i] >= w) ++ans; } inline void voi_add(R int l, R int r) { for (R int i = l; i <= r; ++i) a[i] += w; build(id[l]); } inline void query(R int x) { R int l = x * block, r = (x + 1) * block - 1; cmin(r, n); ans += (r - l + 1) - (std::lower_bound(b + l, b + r + 1, w - tag[x]) - b - l); } int main() { // setfile(); n = FastIn(), q = FastIn(); block = sqrt(n); for (R int i = 1; i <= n; ++i) a[i] = FastIn(); for (R int i = 1; i <= n; ++i) id[i] = i / block; for (R int i = 0; i <= n / block; ++i) build(i); for (R int i = 1; i <= q; ++i) { R char opt = getc(); while (opt < 'A' || opt > 'Z') opt = getc(); R int l = FastIn(), r = FastIn(); w = FastIn(); if (opt == 'A') { ans = 0; if (id[l] == id[r]) voi_query(l, r); else { voi_query(l, (id[l] + 1) * block - 1); voi_query(id[r] * block, r); for (R int i = id[l] + 1; i < id[r]; ++i) query(i); } printf("%d\n", ans ); } else { if (id[l] == id[r]) voi_add(l, r); else { voi_add(l, (id[l] + 1) * block - 1); voi_add(id[r] * block, r); for (R int i = id[l] + 1; i < id[r]; ++i) tag[i] += w; } } } return 0; }
刷题建议:
BZOJ3343 教主的魔法BZOJ3463 [COCI2012] Inspector
YZOJ1653 带区间修改的区间第k小
BZOJ2724 [Violet 6]蒲公英
BZOJ2453 维护队列
BZOJ2821 作诗(Poetize)
相关文章推荐
- Web service是什么?
- android最佳学习路线,学习心得
- 软件工程(C编码实践篇)学习总结
- 【CS50】写在学习前
- 关于这段时间的心历路程
- 第一次写博客
- 《C和指针》学习心得(第一章)
- 个性和共性,对共性的封装。新的语言是如何诞生的
- 我的单片机学习--写给我的一个网友
- c语言面试题总结
- C语言中为什么会出现UL?
- C语言——关键字
- C语言——标识符
- 心得分享:关于对Android的理解,知识点梳理
- android学习总结篇
- 黑马程序员_编程学习心得
- Android 开发学习心得(一)。pull解析xml文件_天气预报
- 计算机专业知识的学习方法,尤其是对基础掌握不多的初学者---个人学习心得
- 关于java以及引申到其他技术的学习方法的小结
- 在VC++中用SQL语句为access加字段时注意事项