线段树

Posted codeDog123

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线段树相关的知识,希望对你有一定的参考价值。

题目:http://acm.hdu.edu.cn/showproblem.php?pid=1166

#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
using namespace std;
#define intervalNum 51000
class node{
public:
    int maximum;
    int minimum;
    int sum;
    int start;
    int end;
    void setVal(int _maximum,int _minimum,int _sum){
        maximum = _maximum;
        minimum = _minimum;
        sum = _sum;
    }
    bool isLeaf(){
        if (start == end){
            return true;
        }
        else{
            return false;
        }
    }
    bool compare(int index){
        if (index>=start&&index<=end){
            return true;
        }
        else{
            return false;
        }
    }
    void setRange(int _start,int _end){
        start = _start;
        end = _end;
    }
    node(int _maximum, int _minimum, int _sum){
        maximum = _maximum;
        minimum = _minimum;
        sum = _sum;
    }
    node(){

    }
};
//递归建立线段树
//tree:线段树的数组
//root:根节点
//start:左区间
//end: 右区间
void buildSegTree(node tree[],int root,int start,int end){
    int mid = (start + end) / 2;
    int lChild = root * 2;
    int rChild = lChild + 1;
    tree[root].setRange(start, end);
    if (start==end){
        int val;
        scanf("%d", &val);
        tree[root].setVal(val,val,val);
        return;
    }
    buildSegTree(tree,root*2,start,mid);
    buildSegTree(tree, root * 2+1, mid+1,end);
    tree[root].setVal(max(tree[lChild].maximum,tree[rChild].maximum),min(tree[lChild].minimum,tree[rChild].minimum),tree[lChild].sum + tree[rChild].sum);
}
//单点更新
//tree:线段树数组
//root:根节点
//index: 更新的区间
//addVal:变化的数值:newValue=oldValue+fluctuation
void updateNode(node tree[],int root,int index,int fluctuation){
    if (tree[root].isLeaf()){
        int newVal = tree[root].sum + fluctuation;
        tree[root].setVal(newVal, newVal, newVal);
        return;
    }
    int lChild = root * 2;
    int rChild = root * 2 + 1;
    if (tree[lChild].compare(index)){
        updateNode(tree, lChild, index, fluctuation);
    }
    else{
        updateNode(tree, rChild, index, fluctuation);
    }
    tree[root].setVal(max(tree[lChild].maximum, tree[rChild].maximum), min(tree[lChild].minimum, tree[rChild].minimum), tree[lChild].sum + tree[rChild].sum);
}
//查询区间和
//tree:线段树数组
//root:根节点
//start:查询开始
//end::查询结束
int querySum(node tree[],int root,int start,int end){
    if (tree[root].start==start&&tree[root].end==end){
        return tree[root].sum;
    }
    int lChild = root * 2;
    int rChild = lChild + 1;
    if (start<=tree[lChild].end&&end >= tree[rChild].start){
        return querySum(tree, lChild, start, tree[lChild].end) + querySum(tree, rChild, tree[rChild].start, end);
    }
    else if (start>=tree[lChild].start&&end <= tree[lChild].end){
        return querySum(tree, lChild, start, end);
    }
    else if (start >= tree[rChild].start&&end <= tree[rChild].end){
        return querySum(tree, rChild, start, end);
    }
    
}
//查询区间最大值
//tree:线段树数组
//root:根节点
//start:查询开始
//end::查询结束
int queryMax(node tree[], int root, int start, int end){
    if (tree[root].start == start&&tree[root].end == end){
        return tree[root].maximum;
    }
    int lChild = root * 2;
    int rChild = lChild + 1;
    int mid = (start + end) / 2;
    if (start <= tree[lChild].end&&end >= tree[rChild].start){
        return max(queryMax(tree, lChild, start, tree[lChild].end), queryMax(tree, rChild, tree[rChild].start, end));
    }
    else if (start >= tree[lChild].start&&end <= tree[lChild].end){
        return queryMax(tree, lChild, start, end);
    }
    else if (start >= tree[rChild].start&&end <= tree[rChild].end){
        return queryMax(tree, rChild, start, end);
    }
}
//查询区间最小值
//tree:线段树数组
//root:根节点
//start:查询开始
//end::查询结束
int queryMin(node tree[], int root, int start, int end){
    if (tree[root].start == start&&tree[root].end == end){
        return tree[root].maximum;
    }
    int lChild = root * 2;
    int rChild = lChild + 1;
    int mid = (start + end) / 2;
    if (start <= tree[lChild].end&&end >= tree[rChild].start){
        return min(queryMin(tree, lChild, start, tree[lChild].end), queryMin(tree, rChild, tree[rChild].start, end));
    }
    else if (start >= tree[lChild].start&&end <= tree[lChild].end){
        return queryMin(tree, lChild, start, end);
    }
    else if (start >= tree[rChild].start&&end <= tree[rChild].end){
        return queryMin(tree, rChild, start, end);
    }
}
int main(){
    node tree[intervalNum * 4]; //大小为区间数的四倍
    int T = -1;
    int N = -1;
    vector<int> result;
    scanf("%d", &T);
    scanf("%d", &N);
    buildSegTree(tree, 1, 1, N);
    for (int i = 1; i <= T; ++i){
        while (true){
            string cmd;
            int argu1, argu2;
            cin >> cmd;
            if (cmd == "Add"){
                cin>> argu1 >> argu2;
                updateNode(tree, 1, argu1, argu2);
            }
            else if(cmd=="Sub"){
                cin >> argu1 >> argu2;
                updateNode(tree, 1, argu1, -argu2);
            }
            else if (cmd == "Query"){
                cin >> argu1 >> argu2;
                result.push_back(querySum(tree, 1, argu1,argu2));
            }
            else if (cmd == "End"){
                 cout <<"case " << i<<":"<<endl;
                for (int i = 0; i < result.size(); ++i){
                    cout << result[i] << endl;
                }
                result.clear();
                break;
            }
        }
    }
    system("pause");
}

 

以上是关于线段树的主要内容,如果未能解决你的问题,请参考以下文章

线段树

CCF(除法):线段树区间修改(50分)+线段树点修改(100分)+线段树(100分)

线段树合并

数据结构——线段树

论线段树:二

线段树