zoukankan      html  css  js  c++  java
  • 线段树

    public class SegmentTree<E> {
    	
    	private E[] tree;
    	private E[] data;
    	private Merger<E> merger;
    	
    	public SegmentTree(E[] arr, Merger<E> merger) {
    		
    		this.merger = merger;
    		
    		data = (E[]) new Object[arr.length];
    		for(int i = 0; i < arr.length; ++ i) {
    			data[i] = arr[i];
    		}
    		
    		tree = (E[]) new Object[4 * arr.length];
    		buildSegmentTree(0, 0, data.length - 1);
    	}
    	
    	// 在treeIndex的位置创建表示区间[l..r]的线段树
    	private void buildSegmentTree(int treeIndex, int l, int r) {
    		
    		if(l == r) {
    			tree[treeIndex] = data[l];
    			return ;
    		}
    		
    		int leftTreeIndex = leftChild(treeIndex);
    		int rightTreeIndex = rightChild(treeIndex);
    		
    		int mid = l + (r - l) / 2;
    		buildSegmentTree(leftTreeIndex, l, mid);
    		buildSegmentTree(rightTreeIndex, mid + 1, r);
    		
    		tree[treeIndex] = merger.merge(tree[leftTreeIndex], tree[rightTreeIndex]);
    	}
    	
    	public int getSize() {
    		return data.length;
    	}
    	
    	public E get(int index) {
    		if(index < 0 || index >= data.length) {
    			throw new IllegalArgumentException("Index is illegal.");
    		}
    		return data[index];
    	}
    	
    	private int leftChild(int index) {
    		return 2 * index + 1;
    	}
    	
    	private int rightChild(int index) {
    		return 2 * index + 2;
    	}
    	
    	// 返回区间[queryL, queryR]的值
    	public E query(int queryL, int queryR) {
    		
    		if(queryL < 0 || queryL >= data.length || queryR < 0 || queryR >= data.length || queryL > queryR) {
    			throw new IllegalArgumentException("Index is illegal.");
    		}
    		return query(0, 0, data.length - 1, queryL, queryR);
    	}
    	
    	// 在以treeIndex为根的线段树中[l..r]的范围里, 搜索区间[queryL, queryR]的值
    	private E query(int treeIndex, int l, int r, int queryL, int queryR) {
    		if(l == queryL && r == queryR) {
    			return tree[treeIndex];
    		}
    		
    		int mid = l + (r - l) / 2;
    		// treeIndex的结点分为[l..mid]和[mid + 1..r]两部分
    		
    		int leftTreeIndex = leftChild(treeIndex);
    		int rightTreeIndex = rightChild(treeIndex);
    		
    		if(queryL >= mid + 1) {
    			return query(rightTreeIndex, mid + 1, r, queryL, queryR);
    		}
    		else if(queryR <= mid) {
    			return query(leftTreeIndex, l, mid, queryL, queryR);
    		}
    		
    		E leftResult = query(leftTreeIndex, l, mid, queryL, mid);
    		E rightResult = query(rightTreeIndex, mid + 1, r, mid + 1, queryR);
    		
    		return merger.merge(leftResult, rightResult);
    	}
    	
    	// 将index位置的值, 更新为e
    	public void set(int index, E e) {
    		
    		if(index < 0 || index >= data.length) {
    			throw new IllegalArgumentException("Index is illegal.");
    		}
    		data[index] = e;
    		set(0, 0, data.length - 1, index, e);
    	}
    	
    	// 在以treeIndex为根的线段树中更新index的值为e
    	private void set(int treeIndex, int l, int r, int index, E e) {
    		
    		if(l == r) {
    			tree[index] = e;
    			return ;
    		}
    		
    		int mid = l + (r - l) / 2;
    		int leftTreeIndex = leftChild(treeIndex);
    		int rightTreeIndex = rightChild(treeIndex);
    		
    		if(index >= mid + 1) {
    			set(rightTreeIndex, mid + 1, r, index, e);
    		}
    		else {	// index <= mid
    			set(leftTreeIndex, l, mid, index, e);
    		}
    		
    		tree[treeIndex] = merger.merge(tree[leftTreeIndex], tree[rightTreeIndex]);
    		
    	}
    	
    	@Override
    	public String toString() {
    		StringBuilder res = new StringBuilder();
    		res.append('[');
    		for(int i = 0; i < tree.length; ++ i) {
    			if(tree[i] != null) {
    				res.append(tree[i]);
    			}
    			else {
    				res.append("null");
    			}
    			
    			if(i != tree.length - 1) {
    				res.append(", ");
    			}
    		}
    		res.append(']');
    		return res.toString();
    	}
    }
    

      

    public interface Merger<E> {
    	E merge(E a, E b);
    }
    

      

    public class Main {
    
    	public static void main(String[] args) {
    
    		Integer[] nums = {-2, 0, 3, -5, 2, -1};
    //		SegmentTree<Integer> segTree = new SegmentTree<>(nums, new Merger<Integer>() {
    //			public Integer merge(Integer a, Integer b) {
    //				return a + b;
    //			}
    //		});
    		SegmentTree<Integer> segTree = new SegmentTree<>(nums, (a, b)->a + b);
    //		System.out.println(segTree);
    		System.out.println(segTree.query(2, 5));
    	}
    
    }
    

      

  • 相关阅读:
    裸二分图匹配poj1469
    洛谷——P2038 无线网络发射器选址
    洛谷—— P1041 传染病控制
    洛谷—— P1784 数独
    Vijos——T 1092 全排列
    Vijos—— T 1359 Superprime
    高并发解决方案--负载均衡
    request 发送多层字典
    June 11th 2017 Week 24th Sunday
    June 10th 2017 Week 23rd Saturday
  • 原文地址:https://www.cnblogs.com/mjn1/p/10882864.html
Copyright © 2011-2022 走看看