zkw樹

藍莓俠發表於2020-12-29

https://sshwy.gitee.io/2018/10/01/55406/
https://www.cnblogs.com/Judge/p/9514862.html
https://blog.csdn.net/DREAM_yao/article/details/108801613

#include<vector>
#include<iostream>
#include<math.h>
#include<limits.h>
using namespace std;

class segmenttree
{
	struct node
	{
		int max;
		bool lazy;
		node(int _max, bool _lazy):max(_max),lazy(_lazy){};
	};
	vector<node>tree;
	int start;
public:
	int query(int left, int right);
	segmenttree(vector<int>&array)
	{
		int h = (int)ceil(log(array.size()/log(2))) + 1;///<線段樹的曾數
		start = (1<<(h-1)) - 1;///<葉節點的開始
		int n = (1<<h)-1;///<線段樹的節點個數
		vector<node>a(n,node(-1,false));
		tree = a;
		for(size_t i=0;i<array.size();++i)
			tree[start+i]=node(array[i], true);
		for(int i=start>>1;; i>>=1)///<樹的曾數
		{	
			for(int j=0; j<i*2+1; ++j)///<橫行
			{	
				node leftNode = tree[2*(i+j)+1];
				node rightNode = tree[2*(i+j)+2];
				if(leftNode.lazy && rightNode.lazy)
					tree[i+j] = node(max(leftNode.max, rightNode.max), true);
				else if(leftNode.lazy && !rightNode.lazy)
					tree[i+j] = leftNode;
			}
			if(0==i)///<i=0得進來一次
				break;
		}	
		return; 
	}
};

int segmenttree::query(int left, int right)
{
	int mmax = max(tree[left].max, tree[right].max);
	left+=start;
	right+=start;
	for(;;left=(left-1)>>1,right=(right-1)>>1)
	{	if(0==left)
		{
			mmax = max(mmax, tree[left].max);
			break;
		}
		///<對於left而言,右子節點在區間內。right的左子節點在區間內
		if(1==left%2) ///<奇數是左子節點,偶數是右子節點
			mmax = max(mmax, tree[left+1].max);
		if(0==right%2)
			mmax = max(mmax, tree[right-1].max);
	}
	return mmax;
}

int main(void)
{
	vector<int>a={1,4,6,8,4,0,9};
	segmenttree b(a);
	cout<<b.query(1,6)<<endl;
	return 0;
}

相關文章