您的位置:首页 > 理论基础 > 数据结构算法

线段树--数据结构专题学习

2016-04-23 00:18 477 查看
这两周是数据结构专题的学习,,被专题的题目虐得死去活来==

 

线段树:简单的说就是把【1,n】的区间二分,【1,(1+n)/2】左子树,【(1+n)/2+1,n】右子树

    就这样一直分下去,直到都是【x,x】这样的区间。这样就构成了一颗树了^-^

          有这样一棵树,我们就可以在节点中储存区间的和啊,区间内的最大值啊,最小值等等。。这就是线段树的附加信息了,也是题目中的重点。。

    我们可以用一个数组(长度为k)储存原区间的初始值,然后根据这个建树,所以这个树的节点数最多为4*K;

    对于每个节点i,其左子树为i*2,右子树为i*2+1,父母节点为i/2。该区间的sum为左右子树区间和的和,最大最小值同理。。。

    线段树的建立,修改,查询都是用递归写的。

    所以在对单个数值时,必定会影响到其祖先节点,所以从上往下写。递归后修改节点信息。

    线段树的查询也是如此,从上向下查询。

    先贴模板

#include <bits/stdc++.h>

using namespace std;

#define MP make_pair
#define PB push_back
typedef long long LL;
typedef pair<int,int> PII;
const double eps=1e-8;
const double pi=acos(-1.0);
const int K=1e6+7;
const int mod=1e9+7;

struct node
{
int max,sum;
int left,right;
};
struct node tree[4*K];
int a[K];
void build(int id,int l,int r)
{
tree[id].left=l,tree[id].right=r;
if(l==r)
tree[id].max=tree[id].sum=a[l];
else
{
build(2*id,l,(l+r)/2),build(2*id+1,(l+r)/2+1,r);
tree[id].max=max(tree[2*id].max,tree[2*id+1].max);
tree[id].sum=tree[2*id].sum+tree[2*id+1].sum;
}
}
int queryMax(int id,int l,int r)
{
if(l==tree[id].left && r==tree[id].right)
return tree[id].max;
int mid=(tree[id].left+tree[id].right)>>1;
if(r<=mid)
return queryMax(id<<1,l,r);
else if(l>=mid+1)
return queryMax((id<<1)+1,l,r);
else
return max(queryMax(id<<1,l,mid),queryMax((id<<1)+1,mid+1,r));
}
int querySum(int id,int l,int r)
{
if (tree[id].left==l&&tree[id].right==r)
return tree[id].sum;
int mid=(tree[id].left+tree[id].right)>>1;
if (r<=mid)
return querySum(id*2,l,r);
else if (l>mid)
return querySum(id*2+1,l,r);
else
return querySum(id*2,l,mid)+querySum(id*2+1,mid+1,r);
}
void update(int id,int pos,int v)
{
if(tree[id].left == tree[id].right)
tree[id].sum=tree[id].max=v;
else
{
int mid=(tree[id].left+tree[id].right)>>1;
if (pos<=mid) update(id*2,pos,v);
else update(id*2+1,pos,v);
tree[id].sum=tree[id*2].sum+tree[id*2+1].sum;
tree[id].max=max(tree[id*2].max,tree[id*2+1].max);
}
}
int main(void)
{

return 0;
}

 

    带区间修改的版本:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <queue>
#include <stack>
#include <map>
#include <vector>
#include <cstdlib>
#include <string>

#define PI acos((double)-1)
#define E exp(double(1))
using namespace std;
#define K 10000
struct node
{
int maxt,sum,lazy;//sum代表节点信息,按题目更改
int left,right;
};
struct node tree[4*K];
int a[K];
void build(int id,int l,int r)
{
tree[id].left=l;tree[id].right=r;tree[id].lazy=0;
if(l==r)
{
tree[id].maxt=tree[id].sum=a[l];
}
else
{
build(2*id,l,(l+r)/2);
build(2*id+1,(l+r)/2+1,r);
tree[id].maxt=max(tree[2*id].maxt,tree[2*id+1].maxt);
tree[id].sum=tree[2*id].sum+tree[2*id+1].sum;
}
}
void pushdowm(int id)
{
if(tree[id].lazy)
{
tree[id*2].lazy=tree[id].lazy;
tree[id*2+1].lazy=tree[id].lazy;
tree[id*2].sum+=tree[id].lazy;
tree[id*2+1].sum+=tree[id].lazy;
tree[id].lazy=0;
}
}
int queryMax(int id,int l,int r)
{
if(l==tree[id].left && r==tree[id].right)
return tree[id].maxt;
int mid=(tree[id].left+tree[id].right)>>1;
int ret=0;
pushdowm(id);
if(r<=mid)
ret=max(ret,queryMax(id<<1,l,r));
else if(l>=mid+1)
ret=max(ret,queryMax((id<<1)+1,l,r));
else
{
int a,b;
a=queryMax(id<<1,l,mid);
b=queryMax((id<<1)+1,mid+1,r);
return max(a,b);
}
return ret;
}
int update(int id,int pos,int v)
{
if(tree[id].left == tree[id].right)
{
tree[id].sum=tree[id].maxt=v;
}
else
{
int mid=(tree[id].left+tree[id].right)>>1;
if (pos<=mid) update(id*2,pos,v);
else update(id*2+1,pos,v);
tree[id].sum=tree[id*2].sum+tree[id*2+1].sum;
tree[id].maxt=max(tree[id*2].maxt,tree[id*2+1].maxt);
}
return 0;
}
void update_interal(int id,int l,int r,int v)
{
if(l==tree[id].left && r==tree[id].right)
{
tree[id].lazy+=v,tree[id].sum+=v;return;
}
pushdowm(id);
int mid=(tree[id].left+tree[id].right)>>1;
if(r<=mid)
update_interal(id*2,l,r,v);
else if(l>mid)
update_interal(id*2+1,l,r,v);
else
{
update_interal(id*2,l,mid,v);
update_interal(id*2+1,mid+1,r,v);
tree[id].sum+=tree[id*2].sum+tree[id*2+1].sum;
}
}
int query(int id,int l,int r)
{
if (tree[id].left==l&&tree[id].right==r)
return tree[id].sum;
else
{
int mid=(tree[id].left+tree[id].right)>>1;
pushdowm(id);
if (r<=mid) return query(id*2,l,r);
else if (l>mid) return query(id*2+1,l,r);
else return query(id*2,l,mid)+query(id*2+1,mid+1,r);
}
}

int main(void)
{
int n,l,r,v;
cin>>n;
for(int i=1;i<=n;i++)
a[i]=i;
build(1,1,n);
printf("%d\n",query(1,1,10));
cin>>l>>r>>v;
update_interal(1,l,r,v);
printf("%d\n",query(1,l,r));
return 0;
}
View Code

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: