使用线段树可以快速的查找某一个节点在若干条线段中出现的次数,时间复杂度为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;
}