基础知识点;
所谓线段树,也就是一颗树,不过这棵树数管的是一个线段,而原本的树管的只是不同的点,其实本质上是一个道理。
线段树算法主要由三部分组成,1建树,2更新3查询。
就以其中第一题为例子
#define lson t<<1
#define rson t<<1|1
#define midl (l+r)/2
#define midr (l+r)/2+1
using namespace std;
const int mm=5e4+9;
class node
{
public:int l,r,beauty;
}rt[mm*4];
/**这一过程主要就是建立树,给树分配其所管理的区域*/
void build(int t,int l,int r)///这就是建树过程
{ rt[t].l=l;rt[t].r=r;
if(rt[t].l==rt[t].r)scanf("%d",&rt[t].beauty);
else
{
build(lson,l,midl);build(rson,midr,r);
rt[t].beauty=rt[lson].beauty+rt[rson].beauty;
}
}
/**对某个区间,或某个点进行更新*/
void update(int t,int id,int num)///这是更新过程
{
if(rt[t].l==rt[t].r&&rt[t].l==id)rt[t].beauty+=num;
else
{
if(rt[lson].r>=id)update(lson,id,num);
else update(rson,id,num);
rt[t].beauty=rt[lson].beauty+rt[rson].beauty;
}
}
/**询问某个区间,或某个点的具体情况*/
int query(int t,int l,int r)///这是查询过程
{
if(rt[t].l==l&&rt[t].r==r)
return rt[t].beauty;
if(rt[lson].r>=r)return query(lson,l,r);
else if(rt[rson].l<=l)return query(rson,l,r);
else return query(lson,l,rt[lson].r)+query(rson,rt[rson].l,r);
}
线段树之单点更新
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=21335#overview
1.简单的单点更新,诸如求某区间的和,或最大值等,而后有单点更新,这是最水的一类,一看便知,不予解释。
2.求逆序数,勉强算一类,这种需要将其离散化, 办法有两个。
(1)用结构体sort,然后给其离散化。
(2)用二分查找标序。
3.序号类型,排队,插队类的。