线段树
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"); }
以上是关于线段树的主要内容,如果未能解决你的问题,请参考以下文章