使用线段树可以快速的查找某一个节点在若干条线段中出现的次数,时间复杂度为O(logN)。而未优化的空间复杂度为2N,因此有时需要离散化让空间压缩。
支持单点更新区间查询,支持区间更新区间查询
对于任意的结点i,其左儿子结点编号为2*i(i<<1),其右儿子编号为2*i+1(i<<1+1)
线段树模板兼HDU1754题解
HDU1754链接:http://acm.hdu.edu.cn/showproblem.php?pid=1754
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #pragma warning(disable:4996) using namespace std; struct seg{ int l, r, grade; }; seg s[800005]; int grades[200005]; /******************************************/ //线段树的递归建树 //1)确定每个结点维护的区间范围 //2)初始化区间信息 //3)递归返回时,用原始信息更新结点信息 /*****************************************/ void build(int l, int r, int i){ s[i].l = l; s[i].r = r; if (l == r){ s[i].grade = grades[l]; return; } int mid = (l + r) >> 1; build(l, mid, i<<1); build(mid + 1, r, (i << 1) | 1); s[i].grade = max(s[i * 2].grade, s[i * 2 + 1].grade); } /*线段树的单点更新*/ void update(int l, int grade,int i){ int mid = (s[i].l + s[i].r) >> 1; if (s[i].l == s[i].r&&s[i].r == l){ s[i].grade = grade; return; } else if (l <= mid) update(l, grade, i << 1); else update(l, grade, (i << 1) | 1); s[i].grade = max(s[i * 2].grade, s[i * 2 + 1].grade); } /*线段树的区间查询*/ int findmax(int l, int r,int i){ int mid = (s[i].l + s[i].r) / 2; if (s[i].l == l&&s[i].r == r) return s[i].grade; else if (r <= mid) return findmax(l, r, i * 2); else if (l >= mid + 1) return findmax(l, r, i * 2 + 1); else{ int a = findmax(l, mid, i * 2); int b = findmax(mid + 1, r, 2 * i + 1); return max(a, b); } } int main() { int n, m; while (scanf("%d %d", &n, &m)!=EOF){ for (int i = 1; i <= n; i++){ scanf("%d", grades + i); } build(1, n, 1); char ch; int a, b; while (m--){ getchar(); scanf("%c %d %d", &ch, &a, &b); if (ch == 'Q'){ printf("%d\n", findmax(a, b, 1)); } else update(a, b,1); } } return 0; }