public Node(double value, ACTION action) { left = right = null; key = value; number = 0; this.action = action; }
public Node() { left = right = null; key = -1; number = 0; action = ACTION.NONE; }
public Node(double value) { left = right = null; key = value; number = 0; action = ACTION.NONE; }
public Node(Node left, Node right) { this.left = left; this.right = right; key = left.key + right.key; number = 0; action = ACTION.NONE; }
public Node(double key, ACTION action, double number, Node left, Node right) { this.left = left; this.right = right; this.key = key; this.number = number; this.action = action; }
public static void Copy(Node from, ref Node to) { to = from; }
private void push(ref Node node, int left, int right) { if (node != null) push(ref node, left, right, ACTION.NONE, 0); }
private void push(ref Node node, int left, int right, ACTION action, double value) { int center = (left + right) / 2; if (node.left != null) push(ref node.left, left, center, node.action, node.number); if (node.right != null) push(ref node.right, center + 1, right, node.action, node.number); if (node.action == ACTION.LIST) node.key = do_action(node.key, action, value); else { double left_value = 0, right_value = 0; if (node.left.action == ACTION.UPDATE) left_value = (center - left + 1) * node.left.number; else if (node.left.action == ACTION.ADD) left_value = node.left.key + (center - left + 1) * node.left.number; else left_value = node.left.key; if (node.right.action == ACTION.UPDATE) right_value = (center - left + 1) * node.right.number; else if (node.right.action == ACTION.ADD) right_value = node.right.key + (center - left + 1) * node.right.number; else right_value = node.right.key; node.key = left_value + right_value; node.action = action; node.number = value; } }
private void mass_update(ref Node node, int left, int right, int query_left, int query_right, ACTION action, double value) { if (query_left > query_right) return; if (left == query_left && right == query_right) { if (left == right) node.key = do_action(node.key, action, value); else if (action == ACTION.UPDATE) { clear(ref node); node.action = action; node.number = value; } else { push(ref node, left, right); node.action = action; node.number += value; } } else { if (node.action == ACTION.ADD || node.action == ACTION.UPDATE) push(ref node, left, right); int center = (left + right) / 2; mass_update(ref node.left, left, center, query_left, Math.Min(query_right, center), action, value); mass_update(ref node.right, center + 1, right, Math.Max(query_left, center + 1), query_right, action, value); double left_value = 0, right_value = 0; if (node.left.action == ACTION.UPDATE) left_value = (center - left + 1) * node.left.number; else if (node.left.action == ACTION.ADD) left_value = node.left.key + (center - left + 1) * node.left.number; else left_value = node.left.key; if (node.right.action == ACTION.UPDATE) right_value = (center - left + 1) * node.right.number; else if (node.right.action == ACTION.ADD) right_value = node.right.key + (center - left + 1) * node.right.number; else right_value = node.right.key; node.key = left_value + right_value; } }
private void pointed_update(ref Node node, int left, int right, int position, ACTION action, double value) { if (left == right) node.key = do_action(node.key, action, value); else { int center = (left + right) / 2; if (node.action == ACTION.UPDATE) push(ref node, left, right); if (position <= center) pointed_update(ref node.left, left, center, position, action, value); else pointed_update(ref node.right, center + 1, right, position, action, value); node.key = node.left.key + node.right.key; } }
private double get(Node node, int left, int right, int query_left, int query_right) { if (query_left > query_right) return 0; if (left == query_left && right == query_right) { if (node.action == ACTION.UPDATE || node.action == ACTION.ADD) push(ref node, left, right); return node.key; } int center = (left + right) / 2; if (node.action == ACTION.NONE) return get(node.left, left, center, query_left, Math.Min(query_right, center)) + get(node.right, center + 1, right, Math.Max(query_left, center + 1), query_right); else if (node.action == ACTION.ADD || node.action == ACTION.UPDATE) { push(ref node, left, right); return get(node.left, left, center, query_left, Math.Min(query_right, center)) + get(node.right, center + 1, right, Math.Max(query_left, center + 1), query_right); } else return node.key; }
private Node Copy(Node node) { if (node == null) return null; else return new Node(node.key, node.action, node.number, Copy(node.left), Copy(node.right)); }
private void clear(ref Node node) { if (node.left != null) clear(ref node.left); if (node.right != null) clear(ref node.right); if (node.action != ACTION.NONE && node.action != ACTION.LIST) { node.action = ACTION.NONE; node.number = 0; } }
public ST() { root = new Node(); length = 0; }
// Constructor public ST(params object[] list) { // Reading an Array List<double> temp = new List<double>(); int len = list.Length; for (int i = 0; i < len; i++) { try { double arg0 = Convert.ToDouble(list[i]); temp.Add(arg0); } catch { double[] arg1 = list[i] as double[]; if (arg1 != null) temp.AddRange(arg1); } } // Preparing an Segment Tree Node node = build(temp, 0, temp.Count - 1); root = new Node(); length = temp.Count; Node.Copy(node, ref root); }