树状数组模板及poj几道简单题
2017-08-06 18:09
411 查看
/*
觉得真是…经历了高考啥都忘了(其实还是当初学得不踏实
现在一点一点再重新来补吧(过了一年再来说这话的我
*/
http://blog.csdn.net/qq_21841245/article/details/43956633 ——MoeO3
也给了我们启示,有时对读入数据排序处理一下,就能收到很好的效果。
还有要注意的就是,树状数组维护的区间下标要从1开始,这道题WA了几次才注意到。
Code:
以前一直都只知道用归并来写的我实在是…个人觉得写起来比归并好写多了。
第一题就是裸的。
第二题还是先通过排序处理一下,做起来就方便不少。
poj 2299 Code:
poj 3067 Code:
写起来和逆序对差不多,从左起插一遍,右起插一遍,得到每个数左边比它大的、比它小的;右边比它大的、比它小的数的个数。其实就是枚举中间那个数,最后乘一乘就是答案。
这道题一个注意点就是题目中的 distinct integers,一开始没注意到,写得又稍微复杂了些,记录了每个数迄今出现的次数 cnt,然后再搞一搞啥的。其实也没啥…。
Code:
一开始还是用while在那里写(太重的Pascal痕迹= =
后来看了模板改成优雅的for了…
Code:
觉得真是…经历了高考啥都忘了(其实还是当初学得不踏实
现在一点一点再重新来补吧(过了一年再来说这话的我
*/
参考资料及模板
http://blog.csdn.net/lawrence_jang/article/details/8054173 ——Lawrence_Janghttp://blog.csdn.net/qq_21841245/article/details/43956633 ——MoeO3
poj题目小集
poj 2352
看上去是个二维的题,事实上因为读入数据是按序排列的,所以可以直接转化成一维来做,就是个裸的单点修改区间查询的树状数组了。也给了我们启示,有时对读入数据排序处理一下,就能收到很好的效果。
还有要注意的就是,树状数组维护的区间下标要从1开始,这道题WA了几次才注意到。
Code:
#include <cstdio> #include <cstring> #define maxn 32001 #define maxm 15010 inline int lowbit(int x) { return x & (-x); } int n, level[maxm], c[maxn + 10]; void update(int x) { while (x <= maxn) { ++c[x]; x += lowbit(x); } } int query(int x) { int ret = 0; while (x) { ret += c[x]; x -= lowbit(x); } return ret; } void work() { memset(level, 0, sizeof(level)); memset(c, 0, sizeof(c)); for (int i = 0; i < n; ++i) { int x, y; scanf("%d%d", &x, &y); update(++x); ++level[query(x)]; } for (int i = 1; i <= n; ++i) printf("%d\n", level[i]); } int main() { while (scanf("%d", &n) != EOF) work(); return 0; }
poj 2299 & poj 3067
两道用 树状数组 来解决 逆序对 的问题。以前一直都只知道用归并来写的我实在是…个人觉得写起来比归并好写多了。
第一题就是裸的。
第二题还是先通过排序处理一下,做起来就方便不少。
poj 2299 Code:
#include <cstdio> #include <cstring> #include <algorithm> #define maxn 500010 using namespace std; typedef long long LL; struct node { int val, p; bool operator < (const node& nd) const { return val < nd.val; } }a[maxn]; int b[maxn], c[maxn], n; inline int lowbit(int x) { return x & (-x); } int query(int x) { int ret = 0; while (x) { ret += c[x]; x -= lowbit(x); } return ret; } void add(int x) { while (x <= n) { // printf("%d\n", x); ++c[x]; x += lowbit(x); } } void work() { memset(c, 0, sizeof(c)); for (int i = 1; i <= n; ++i) { scanf("%d", &a[i].val); a[i].p = i; } sort(a + 1, a + n + 1); for (int i = 1; i <= n; ++i) b[a[i].p] = i; LL sum = 0; for (int i = 1; i <= n; ++i) { sum += i - 1 - query(b[i]); add(b[i]); } printf("%lld\n", sum); } int main() { freopen("in.txt", "r", stdin); while (scanf("%d", &n) != EOF && n) work(); return 0; }
poj 3067 Code:
#include <cstdio> #include <cstring> #include <algorithm> #define maxn 1010 #define maxk 1000010 int c[maxn], kas, n, m, k; using namespace std; typedef long long LL; struct Edge { int x, y; }e[maxk]; bool cmp(Edge a, Edge b) { return a.x < b.x || (a.x == b.x && a.y < b.y); } inline int lowbit(int x) { return x & (-x); } int query(int x) { int ret = 0; while (x) { ret += c[x]; x -= lowbit(x); } return ret; } void add(int x) { while (x <= m) { ++c[x]; x += lowbit(x); } } void work() { memset(c, 0, sizeof(c)); scanf("%d%d%d", &n, &m, &k); for (int i = 0; i < k; ++i) scanf("%d%d", &e[i].x, &e[i].y); sort(e, e + k, cmp); LL sum = 0; for (int i = 0; i < k; ++i) { sum += i - query(e[i].y); add(e[i].y); } printf("Test case %d: %lld\n", ++kas, sum); } int main() { int T; scanf("%d", &T); while (T--) work(); return 0; }
poj 3928
要求一个序列中单调增或者单调减的三元组的个数总和。写起来和逆序对差不多,从左起插一遍,右起插一遍,得到每个数左边比它大的、比它小的;右边比它大的、比它小的数的个数。其实就是枚举中间那个数,最后乘一乘就是答案。
这道题一个注意点就是题目中的 distinct integers,一开始没注意到,写得又稍微复杂了些,记录了每个数迄今出现的次数 cnt,然后再搞一搞啥的。其实也没啥…。
Code:
#include <cstdio> #include <cstring> #define maxn 100000 #define maxm 20010 int a[maxm], c[maxn + 10], cnt[maxn + 10], le1[maxm], le2[maxm], gr1[maxm], gr2[maxm]; typedef long long LL; inline int lowbit(int x) { return x & (-x); } void add(int x) { while (x <= maxn) { ++c[x]; x += lowbit(x); } } int query(int x) { int ret = 0; while (x) { ret += c[x]; x -= lowbit(x); } return ret; } void work() { int n; scanf("%d", &n); for (int i = 0; i < n; ++i) scanf("%d", &a[i]); memset(c, 0, sizeof(c)); for (int i = 0; i < n; ++i) { int x = a[i]; le1[i] = query(x); gr1[i] = i - le1[i]; add(x); } memset(c, 0, sizeof(c)); for (int i = n - 1; i >= 0; --i) { int x = a[i]; le2[i] = query(x); gr2[i] = (n - 1 - i) - le2[i]; add(x); } // for (int i = 1; i < n - 1; ++i) { // printf("%d %d %d %d\n", le1[i], le2[i], gr1[i], gr2[i]); // } LL ans = 0; for (int i = 1; i < n - 1; ++i) { ans += le1[i] * gr2[i] + le2[i] * gr1[i]; } printf("%lld\n", ans); } int main() { freopen("in.txt", "r", stdin); int T; scanf("%d", &T); while (T--) work(); return 0; }
poj1195
裸的二维树状数组一开始还是用while在那里写(太重的Pascal痕迹= =
后来看了模板改成优雅的for了…
Code:
#include <cstdio> #include <cstring> #define maxn 1030 int c[maxn][maxn], s, n; inline int lowbit(int x) { return x & (-x); } void update(int x, int y, int a) { for (int i = x; i <= n; i += lowbit(i)) { for (int j = y; j <= n; j += lowbit(j)) { c[i][j] += a; } } } int query(int x, int y) { if (x == 0 || y == 0) return 0; int ret = 0; for (int i = x; i; i -= lowbit(i)) { for (int j = y; j; j -= lowbit(j)) { ret += c[i][j]; } } return ret; } void work() { memset(c, 0, sizeof(c)); while (scanf("%d", &s)) { if (s == 3) return; if (s == 1) { int x, y, a; scanf("%d%d%d", &x, &y, &a); ++x; ++y; update(x, y, a); } else { int l, b, r, t; scanf("%d%d%d%d", &l, &b, &r, &t); ++r; ++t; printf("%d\n", query(r, t) - query(l, t) - query(r, b) + query(l, b)); } } } int main() { freopen("in.txt", "r", stdin); while (scanf("%d%d", &s, &n) != EOF) work(); return 0; }
相关文章推荐
- 模板(线段树 + 树状数组 + 区间修改 + 区间查询)eg:POJ 3468 - A Simple Problem with Integers
- poj 2352(简单树状数组)
- POJ 2352 Stars(简单树状数组)
- poj 3486 A Simple Problem with Integers(树状数组第三种模板改段求段)
- POJ 2309树状数组的简单变型
- 文章标题 POJ 1195 :Mobile phones(二维树状数组 模板)
- POJ 2481 Cows 简单树状数组区间覆盖
- (简单) POJ 3321 Apple Tree,树链剖分+树状数组。
- POJ1195 Mobile phones(简单二维树状数组)
- poj 2352 Stars(简单树状数组)此题也可以用线段树来做
- (简单) POJ 1195 Mobile phones,二维树状数组。
- poj 1195 二维树状数组 及二维树状数组模板
- poj 1195 (二维树状数组入门,模板题)
- POJ 1656 二维树状数组简单应用
- 【二维树状数组--模板】poj 2155 Matrix、poj 1195 Mobile phones
- (模板题)poj 2352 Stars(树状数组)
- POJ-2481 Cows 树状数组
- POJ2155【二维树状数组模板】
- 【树状数组】 ◆POJ 3321◆ Apple Tree
- poj 几道简单的二分题