【参考代码】mz线段树基本操作训练
来源:互联网 发布:gbase 8a sql参考手册 编辑:程序博客网 时间:2024/05/29 11:07
QAQ为什么高一小朋友们的题都这么难。。
代码仅供参考,禁止照抄哦 = v =
说明一下:read()函数是读入优化,你们直接写scanf就行了。namespace只是为了封装,可以不要。
然后我线段树的姿势可能和你们老师讲的不太一样,个人觉得这样写起来简洁一些,而且效率高。
Promble A
原题是hdu1166。简单的点修改和区间查询。因为太水了我就写的树状数组 = =
#include <cstdio>#include <iostream>#include <cstring> #define lowbit(i) (i & -i)using namespace std;int read(){int sign = 1, n = 0; char c = getchar();while(c < '0' || c > '9'){ if(c == '-') sign = -1; c = getchar(); }while(c >= '0' && c <= '9') { n = n*10 + c-'0'; c = getchar(); }return sign*n;}const int Nmax = 50005;int N, a[Nmax];namespace BIT {int d[Nmax];inline void init() { memset(d + 1, 0, sizeof(d[0]) * N); }inline void Add(int pos, int x) {for (int i = pos; i <= N; i += lowbit(i)) d[i] += x;}inline int Query(int pos){int res = 0;for (int i = pos; i; i -= lowbit(i)) res += d[i];return res;}}int main(){for (int T = read(), cas = 1; T --; ++ cas) {N = read();for (int i = 1; i <= N; ++ i) a[i] = read();using namespace BIT; init();for (int i = 1; i <= N; ++ i) Add(i, a[i]);char s[10]; printf("Case %d:\n", cas);while (~scanf("%s", s) && s[0] != 'E') {int i = read(), j = read();if (s[0] == 'A') Add(i, j);else if (s[0] == 'S') Add(i, -j);else printf("%d\n", Query(j) - Query(i - 1));}}return 0;}
Problem B
原题是hdu1754。记录最大值即可。
#include <cstdio>#include <iostream>#include <algorithm>#define lc (u << 1)#define rc (u << 1 | 1)using namespace std;int read(){int sign = 1, n = 0; char c = getchar();while(c < '0' || c > '9'){ if(c == '-') sign = -1; c = getchar(); }while(c >= '0' && c <= '9') { n = n*10 + c-'0'; c = getchar(); }return sign*n;}const int Nmax = 200005;int N, M;int a[Nmax];namespace SegmentTree {int mmax[Nmax << 2];inline void build(int u, int l, int r){if (l == r) {mmax[u] = a[l];return;}int mid = (l + r) >> 1;build(lc, l, mid); build(rc, mid + 1, r);mmax[u] = max(mmax[lc], mmax[rc]);}inline void update(int u, int l, int r, const int &pos, const int &x){if (l == r) {mmax[u] = x;return;}int mid = (l + r) >> 1;if (pos <= mid) update(lc, l, mid, pos, x);else update(rc, mid + 1, r, pos, x);mmax[u] = max(mmax[lc], mmax[rc]);}inline int Query(int u, int l, int r, int L, int R){if (l == L && r == R) return mmax[u];int mid = (l + r) >> 1;if (R <= mid) return Query(lc, l, mid, L, R);else if (L > mid) return Query(rc, mid + 1, r, L, R);return max(Query(lc, l, mid, L, mid), Query(rc, mid + 1, r, mid + 1, R));}}int main(){while (~scanf("%d%d", &N, &M)) {for (int i = 1; i <= N; ++ i) a[i] = read();using namespace SegmentTree;build(1, 1, N); char c; int A, B;while (M --) {scanf(" %c", &c); A = read(); B = read();if (c == 'Q') printf("%d\n", Query(1, 1, N, A, B));else update(1, 1, N, A, B);}}return 0;}
Problem C
原题hdu1698。记录当前区间的颜色即可,如果不止一种颜色,就标记为0。修改的时候记得下放标记。
#include <cstdio>#include <iostream>#define lc (u << 1)#define rc (u << 1 | 1)using namespace std;int read(){int sign = 1, n = 0; char c = getchar();while(c < '0' || c > '9'){ if(c == '-') sign = -1; c = getchar(); }while(c >= '0' && c <= '9') { n = n*10 + c-'0'; c = getchar(); }return sign*n;}const int Nmax = 100005;namespace SegmentTree {int lazy[Nmax << 2];void build(int u, int l, int r) {lazy[u] = 1; if (l == r) return; int mid = (l + r) >> 1;build(lc, l, mid); build(rc, mid + 1, r);} inline void Modify(int u, int l, int r, int L, int R, const int &x) {if (lazy[u] == x || (l == L && r == R)) { lazy[u] = x; return; }if (lazy[u]) { lazy[lc] = lazy[rc] = lazy[u]; lazy[u] = 0; }int mid = (l + r) >> 1;if (R <= mid) Modify(lc, l, mid, L, R, x);else if (L > mid) Modify(rc, mid + 1, r, L, R, x);else {Modify(lc, l, mid, L, mid, x);Modify(rc, mid + 1, r, mid + 1, R, x);}}inline int Query(int u, int l, int r) {if (lazy[u]) return (r - l + 1) * lazy[u];int mid = (l + r) >> 1;return Query(lc, l, mid) + Query(rc, mid + 1, r); }}int N, Q;int main(){for (int T = read(), cas = 1; T --; ++ cas) {N = read(), Q = read(); using namespace SegmentTree;build(1, 1, N);for (int l, r, x; Q --; ) {l = read(), r = read(), x = read();Modify(1, 1, N, l, r, x);}printf("Case %d: The total value of the hook is %d.\n", cas, Query(1, 1, N));}return 0;}
Problem D
原题hdu3308。记录左边连续上升的长度,右边连续上升的长度和整个区间连续上升的长度。Pushup的时候合并一下就行了,然后Query横跨两个区间的时候也要考虑是否可以连续。
#include <cstdio>#include <iostream>#include <algorithm>using namespace std;int read(){int sign = 1, n = 0; char c = getchar();while(c < '0' || c > '9'){ if(c == '-') sign = -1; c = getchar(); }while(c >= '0' && c <= '9') { n = n*10 + c-'0'; c = getchar(); }return sign*n;}const int Nmax = 100005;int N, M;int a[Nmax];#define lc (u << 1)#define rc (u << 1 | 1)namespace SegmentTree {int lsum[Nmax << 2], rsum[Nmax << 2], msum[Nmax << 2];inline void Push_up(int u, int l, int r, int m){if (a[m] < a[m + 1]) {lsum[u] = (lsum[lc] == m - l + 1) ? (m - l + 1 + lsum[rc]) : lsum[lc];rsum[u] = (rsum[rc] == r - m) ? (r - m + rsum[lc]) : rsum[rc];msum[u] = max(max(msum[lc], msum[rc]), lsum[rc] + rsum[lc]);} else {lsum[u] = lsum[lc]; rsum[u] = rsum[rc];msum[u] = max(msum[lc], msum[rc]);} }void build(int u, int l, int r){if (l == r) {lsum[u] = rsum[u] = msum[u] = 1;return;}int mid = (l + r) >> 1;build(lc, l, mid); build(rc, mid + 1, r);Push_up(u, l, r, mid);}void Modify(int u, int l, int r, const int &pos, const int &x){if (l == r) { a[pos] = x; return; }int mid = (l + r) >> 1;if (pos <= mid) Modify(lc, l, mid, pos, x);else Modify(rc, mid + 1, r, pos, x);Push_up(u, l, r, mid);}int Query(int u, int l, int r, int L, int R) {if (L == l && R == r) return msum[u];int mid = (l + r) >> 1;if (R <= mid) return Query(lc, l, mid, L, R);if (L > mid) return Query(rc, mid + 1, r, L, R);int res = max(Query(lc, l, mid, L, mid), Query(rc, mid + 1, r, mid + 1, R));if (a[mid] < a[mid + 1]) res = max(res, min(mid - L + 1, rsum[lc]) + min(R - mid, lsum[rc]));return res;}}int main(){for (int T = read(); T --; ) {N = read(), M = read();for (int i = 1; i <= N; ++ i) a[i] = read();using namespace SegmentTree;build(1, 1, N); char s[10]; int a, b;while (M --) {scanf("%s", s); a = read(); b = read();if (s[0] == 'Q') printf("%d\n", Query(1, 1, N, a + 1, b + 1));else Modify(1, 1, N, a + 1, b);}}return 0;}
Problem E
原题hdu1542。扫描线入门。建议以后要准备省选&NOI的同学掌握。
具体做法请自行百度。建议自学,这种东西我估计老师也没法给你们讲懂的。
另外用到了离散化,这个也要先去学习一下。
#include <cstdio>#include <iostream>#include <algorithm>using namespace std;const int Lmax = 205;int N;struct Line {double x, down, up;int cover;bool operator < (const Line &b) const { return x < b.x; }}L[Lmax];double h[Lmax];#define lc (u << 1)#define rc (u << 1 | 1)namespace SegmentTree {int cover[Lmax << 2]; double len[Lmax << 2];inline void build(int u, int l, int r) {cover[u] = len[u] = 0;if (l == r) return;int mid = (l + r) >> 1;build(lc, l, mid); build(rc, mid + 1, r);}inline void Push_up(int u, int l, int r){if (cover[u]) len[u] = h[r] - h[l - 1];else len[u] = (l == r) ? 0 : len[lc] + len[rc];}void Update(int u, int l, int r, int L, int R, const int &x){if (l == L && r == R) {cover[u] += x;Push_up(u, l, r); return;} int mid = (l + r) >> 1;if (R <= mid) Update(lc, l, mid, L, R, x);else if (L > mid) Update(rc, mid + 1, r, L, R, x);else {Update(lc, l, mid, L, mid, x);Update(rc, mid + 1, r, mid + 1, R, x);}Push_up(u, l, r);}}int main(){ios :: sync_with_stdio(false);int cas = 0, M; while (cin >> N && N) {M = 0; double x1, x2, y1, y2;for (int i = 1; i <= N; ++ i) {cin >> x1 >> y1 >> x2 >> y2;h[M] = y1;L[M ++] = (Line) { x1, y1, y2, 1 };h[M] = y2;L[M ++] = (Line) { x2, y1, y2, -1 };}sort(h, h + M);N = unique(h, h + M) - h; sort(L, L + M); -- M;printf("Test case #%d\n", ++cas);using namespace SegmentTree; double ans = 0. ; build(1, 1, N - 1);for (int i = 0; i < M; ++ i) {int l = lower_bound(h, h + N, L[i].down) - h + 1;int r = lower_bound(h, h + N, L[i].up) - h;Update(1, 1, N - 1, l, r, L[i].cover);ans += len[1] * (L[i + 1].x - L[i].x);}printf("Total explored area: %0.2f\n\n", ans);}return 0;}
0 0
- 【参考代码】mz线段树基本操作训练
- 基本线段树操作
- 蓝桥杯 算法训练 操作格子 (最基本的线段树)
- 算法训练 操作格子 (线段树)
- 蓝桥杯 算法训练 操作格子 (线段树)
- 算法训练 操作格子 线段树
- 【MZ】hdu 4117 AC自动机DP + 线段树优化
- 线段树 递归 基本操作
- 数据结构--线段树--基本操作
- 线段树的基本操作
- 线段树及其基本操作
- 线段树的基本操作
- 线段树基本操作讲解
- 线段树基本操作C++
- 蓝桥杯 算法训练 操作格子 (线段树)
- 蓝桥杯 ALGO-8 算法训练 操作格子(线段树)
- [蓝桥杯]算法训练 操作格子-链式线段树
- 线段树基本操作模板 hdu1166 hdu1754
- poj 2397
- HDU 3333 Turing Tree (离线询问+线段树)
- 下载文件时libcore.io.ErrnoException: open failed: EISDIR (Is a directory)
- 项目整合管理
- 需求是我想用几个复选框控制每根柱子的显示和隐藏
- 【参考代码】mz线段树基本操作训练
- SSL密钥协商过程详解
- Uva 101 the block problem 木块问题(算法竞赛经典入门)STL vector
- jquery.newplaceholder.js
- Android中在XML文件里@+id/和@id/的区别
- Remove Nth Node From End of List
- 《剑指Offer》学习笔记--面试题9:斐波那契数列
- USB的VID和PID,以及分类(Class,SubClass,Protocol)
- 命令行运行java程序,将控制台日志保存到指定文件