ACM数据结构-线段树

1.维护区间最大最小值模板(以维护最小值为例)

#include<iostream> 
#include<stdio.h>

#define LEN 11
#define MAX 1<<30

using namespace std;

int arr[LEN]={1,3,7,6,8,5,3,2,7,2,9};
int st[LEN*3];    //segment tree
int n;

void init(int len){
    n=1;
    while(n<len) n*=2;    //不断乘以2,知道>=len
    for(int i=0;i<n;i++) st[i]=MAX;
}

void update(int p,int v){    //我们有n(len的二次幂扩增)个叶子作为线段元素 
    p+=n-1;            //地址重定向,变为叶子节点所在地址
    st[p]=v;
    while(p>0){
        p=(p-1)/2;    //向上跳转到父节点
        st[p]=min(st[p*2+1],st[p*2+2]);    //更新父节点 
    } 
}

//    查询[a,b)的最小值,当前函数的查询是[l,r) 。当前根节点为p 
int query(int a,int b,int p,int l,int r){//外部调用: query(a,b,0,0,n)
    //如果[a,b)与[l,r)不相交
    if(a>=r || b<=l)
        return MAX;
    //如果[a,b)包裹住了[l,r)
    if(a<=l && b>=r)
        return st[p];
    //其他情况,二分进行查询 
    int v1=query(a,b,p*2+1,l,(l+r)/2);
    int v2=query(a,b,p*2+2,(l+r)/2,r);
    return min(v1,v2);
} 

int main(){
    init(LEN);
    int i,a,b;
    for(i=0;i<LEN;i++)
        update(i,arr[i]);
    while(1){
        scanf("%d%d",&a,&b);
        printf("%d\n",query(a,b,0,0,n));
    }
    return 0;
} 

 


 

2.维护区间和的模板

数据结构:

struct node
{
    int left,right;
    int num;
}tree[2000010];

建树:

void build(int left,int right,int index)    //build(1,n,1);
{
    he++;
    tree[index].left=left;
    tree[index].right=right;
    if(left==right)
        return ;
    int mid=(right+left)/2;
    build(left,mid,index*2);
    build(mid+1,right,index*2+1);
}

单点修改:

void my_plus(int index,int dis,int k)    //将索引为p的元素增加k 
{                                        // my_plus(1,p,k)
    tree[index].num+=k;
    if(tree[index].left==tree[index].right)    //没有叶子节点 
        return ;
    if(dis<=tree[index*2].right)
        my_plus(index*2,dis,k);
    if(dis>=tree[index*2+1].left)
        my_plus(index*2+1,dis,k);
}

单点查询:

int search(int index,int dis) //调用方法:查找索引为p的元素:search(1,p)
{
    if(tree[index].left==tree[index].right && tree[index].left==dis)
        return tree[index].num;
    if(dis<=tree[index*2].right)
        search(index*2,dis);
    if(dis>=tree[index*2+1].left)
        search(index*2+1,dis);
}

区间修改:

    void pls(int index,int l,int r,int k)
    {
        if(tree[index].left>=l && tree[index].right<=r)
        {
            tree[index].num+=k;
            return ;
        }
        if(tree[index*2].right>=l)
           pls(index*2,l,r,k);
        if(tree[index*2+1].left<=r)
           pls(index*2+1,l,r,k);
    }

区间查询:

void search(int index,int l,int r)
{
    //cout<<index<<" ";
    if(tree[index].left>=l && tree[index].right<=r)
    {
        ans+=tree[index].num;
        return ;
    }
    if(tree[index*2].right>=l)
        search(index*2,l,r);
    if(tree[index*2+1].left<=r)
        search(index*2+1,l,r);
}

 


 

 

3.模板编写练习:

 

posted @ 2018-02-15 15:21  TQCAI  阅读(217)  评论(0编辑  收藏  举报