线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。
使用线段树可以快速的查找某一个节点在若干条线段中出现的次数,时间复杂度为O(logN)。而未优化的空间复杂度为2N,因此有时需要离散化让空间压缩。
这里附上最简单线段树题目:
/*
Author:Yangxiangyu
Pid:HDU 1754 I hate it
简单线段树
*/
#include<stdio.h>
#define MAXN 200000
struct node
{
int left,right,mid,value;
} segment_tree[MAXN<<2];
int n,m;
int max(int a,int b)
{
return a>b?a:b;
}
void build(int left,int right,int num)
{
segment_tree[num].left=left;
segment_tree[num].right=right;
segment_tree[num].mid=(left+right)>>1;
segment_tree[num].value=0;
if(left==right)return;
build(left,segment_tree[num].mid,num<<1);
build(segment_tree[num].mid+1,right,(num<<1)+1);
}
void insert(int pos,int value,int num)
{
if(segment_tree[num].value<value)segment_tree[num].value=value;
if(segment_tree[num].left==segment_tree[num].right)return;
if(pos<=segment_tree[num].mid)insert(pos,value,num<<1);
else insert(pos,value,(num<<1)+1);
}
int query(int left,int right,int num)
{
if(left==segment_tree[num].left&&right==segment_tree[num].right)
return segment_tree[num].value;
if(segment_tree[num].left==segment_tree[num].right)
return segment_tree[num].value;
if(left<=segment_tree[num].mid)
{
if(right<=segment_tree[num].mid)
return query(left,right,num<<1);
return max(query(left,segment_tree[num].mid,num<<1),query(segment_tree[num].mid+1,right,(num<<1)+1));
}
return query(left,right,(num<<1)+1);
}
void update(int pos,int value,int num)
{
if(segment_tree[num].left==pos&&segment_tree[num].right==pos)
{
segment_tree[num].value=value;
return;
}
if(pos>=segment_tree[num].left&&pos<=segment_tree[num].mid)
{
segment_tree[num].value=value;
update(pos,value,num<<1);
}
if(pos<=segment_tree[num].right&&pos>segment_tree[num].mid)
{
segment_tree[num].value=value;
update(pos,value,(num<<1)+1);
}
}
int main()
{
int i,j,val,a,b;
char str[10];
while(~scanf("%d%d",&n,&m))
{
build(1,n,1);
for(i=1; i<=n; i++)
{
scanf("%d",&val);
insert(i,val,1);
}
while(m--)
{
scanf("%s%d%d",str,&a,&b);
if(str[0]=='Q')printf("%d\n",query(a,b,1));
else update(a,b,1);
}
}
}