Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //https://github.com/williamfiset/Algorithms/tree/master/com/williamfiset/algorithms/geometry GITHUB GEO algos
- //https://geomalgorithms.com/
- //http://tutorial.math.lamar.edu/pdf/Calculus_Cheat_Sheet_All.pdf
- //http://static.pdesas.org/content/documents/Keystone_Formula_Sheet-Geometry.pdf
- //http://tutorial.math.lamar.edu/pdf/Trig_Cheat_Sheet.pdf
- //https://www.tug.org/texshowcase/cheat.pdf
- //Segment tree min query
- // Java Program to show segment tree operations like construction,
- // query and update
- import java.util.*;
- // Java Program to show segment tree operations like construction,
- // query and update
- class SegmentTree
- {
- int st[]; // The array that stores segment tree nodes
- /* Constructor to construct segment tree from given array. This
- constructor allocates memory for segment tree and calls
- constructSTUtil() to fill the allocated memory */
- SegmentTree(int arr[], int n)
- {
- // Allocate memory for segment tree
- //Height of segment tree
- int x = (int) (Math.ceil(Math.log(n) / Math.log(2)));
- //Maximum size of segment tree
- int max_size = 2 * (int) Math.pow(2, x) - 1;
- st = new int[max_size]; // Memory allocation
- constructSTUtil(arr, 0, n - 1, 0);
- }
- // A utility function to get the middle index from corner indexes.
- int getMid(int s, int e) {
- return s + (e - s) / 2;
- }
- /* A recursive function to get the sum of values in given range
- of the array. The following are parameters for this function.
- st --> Pointer to segment tree
- si --> Index of current node in the segment tree. Initially
- 0 is passed as root is always at index 0
- ss & se --> Starting and ending indexes of the segment represented
- by current node, i.e., st[si]
- qs & qe --> Starting and ending indexes of query range */
- int getSumUtil(int ss, int se, int qs, int qe, int si)
- {
- // If segment of this node is a part of given range, then return
- // the sum of the segment
- if (qs <= ss && qe >= se)
- return st[si];
- // If segment of this node is outside the given range
- if (se < qs || ss > qe)
- return 0;
- // If a part of this segment overlaps with the given range
- int mid = getMid(ss, se);
- return getSumUtil(ss, mid, qs, qe, 2 * si + 1) +
- getSumUtil(mid + 1, se, qs, qe, 2 * si + 2);
- }
- /* A recursive function to update the nodes which have the given
- index in their range. The following are parameters
- st, si, ss and se are same as getSumUtil()
- i --> index of the element to be updated. This index is in
- input array.
- diff --> Value to be added to all nodes which have i in range */
- void updateValueUtil(int ss, int se, int i, int diff, int si)
- {
- // Base Case: If the input index lies outside the range of
- // this segment
- if (i < ss || i > se)
- return;
- // If the input index is in range of this node, then update the
- // value of the node and its children
- st[si] = st[si] + diff;
- if (se != ss) {
- int mid = getMid(ss, se);
- updateValueUtil(ss, mid, i, diff, 2 * si + 1);
- updateValueUtil(mid + 1, se, i, diff, 2 * si + 2);
- }
- }
- // The function to update a value in input array and segment tree.
- // It uses updateValueUtil() to update the value in segment tree
- void updateValue(int arr[], int n, int i, int new_val)
- {
- // Check for erroneous input index
- if (i < 0 || i > n - 1) {
- System.out.println("Invalid Input");
- return;
- }
- // Get the difference between new value and old value
- int diff = new_val - arr[i];
- // Update the value in array
- arr[i] = new_val;
- // Update the values of nodes in segment tree
- updateValueUtil(0, n - 1, i, diff, 0);
- }
- // Return sum of elements in range from index qs (quey start) to
- // qe (query end). It mainly uses getSumUtil()
- int getSum(int n, int qs, int qe)
- {
- // Check for erroneous input values
- if (qs < 0 || qe > n - 1 || qs > qe) {
- System.out.println("Invalid Input");
- return -1;
- }
- return getSumUtil(0, n - 1, qs, qe, 0);
- }
- // A recursive function that constructs Segment Tree for array[ss..se].
- // si is index of current node in segment tree st
- int constructSTUtil(int arr[], int ss, int se, int si)
- {
- // If there is one element in array, store it in current node of
- // segment tree and return
- if (ss == se) {
- st[si] = arr[ss];
- return arr[ss];
- }
- // If there are more than one elements, then recur for left and
- // right subtrees and store the sum of values in this node
- int mid = getMid(ss, se);
- st[si] = constructSTUtil(arr, ss, mid, si * 2 + 1) +
- constructSTUtil(arr, mid + 1, se, si * 2 + 2);
- return st[si];
- }
- // Driver program to test above functions
- public static void main(String args[])
- {
- int arr[] = {1, 3, 5, 7, 9, 11};
- int n = arr.length;
- SegmentTree tree = new SegmentTree(arr, n);
- // Build segment tree from given array
- // Print sum of values in array from index 1 to 3
- System.out.println("Sum of values in given range = " +
- tree.getSum(n, 1, 3));
- // Update: set arr[1] = 10 and update corresponding segment
- // tree nodes
- tree.updateValue(arr, n, 1, 10);
- // Find sum after the value is updated
- System.out.println("Updated sum of values in given range = " +
- tree.getSum(n, 1, 3));
- }
- }
- //Binary indexed tree
- // Java program to demonstrate lazy
- // propagation in segment tree
- import java.util.*;
- import java.lang.*;
- import java.io.*;
- class BinaryIndexedTree
- {
- // Max tree size
- final static int MAX = 1000;
- static int BITree[] = new int[MAX];
- /* n --> No. of elements present in input array.
- BITree[0..n] --> Array that represents Binary
- Indexed Tree.
- arr[0..n-1] --> Input array for whic prefix sum
- is evaluated. */
- // Returns sum of arr[0..index]. This function
- // assumes that the array is preprocessed and
- // partial sums of array elements are stored
- // in BITree[].
- int getSum(int index)
- {
- int sum = 0; // Iniialize result
- // index in BITree[] is 1 more than
- // the index in arr[]
- index = index + 1;
- // Traverse ancestors of BITree[index]
- while(index>0)
- {
- // Add current element of BITree
- // to sum
- sum += BITree[index];
- // Move index to parent node in
- // getSum View
- index -= index & (-index);
- }
- return sum;
- }
- // Updates a node in Binary Index Tree (BITree)
- // at given index in BITree. The given value
- // 'val' is added to BITree[i] and all of
- // its ancestors in tree.
- public static void updateBIT(int n, int index,
- int val)
- {
- // index in BITree[] is 1 more than
- // the index in arr[]
- index = index + 1;
- // Traverse all ancestors and add 'val'
- while(index <= n)
- {
- // Add 'val' to current node of BIT Tree
- BITree[index] += val;
- // Update index to that of parent
- // in update View
- index += index & (-index);
- }
- }
- /* Function to construct fenwick tree
- from given array.*/
- void constructBITree(int arr[], int n)
- {
- // Initialize BITree[] as 0
- for(int i=1; i<=n; i++)
- BITree[i] = 0;
- // Store the actual values in BITree[]
- // using update()
- for(int i = 0; i < n; i++)
- updateBIT(n, i, arr[i]);
- }
- // Main function
- public static void main(String args[])
- {
- int freq[] = {2, 1, 1, 3, 2, 3,
- 4, 5, 6, 7, 8, 9};
- int n = freq.length;
- BinaryIndexedTree tree = new BinaryIndexedTree();
- // Build fenwick tree from given array
- tree.constructBITree(freq, n);
- System.out.println("Sum of elements in arr[0..5]"+
- " is "+ tree.getSum(5));
- // Let use test the update operation
- freq[3] += 6;
- // Update BIT for above change in arr[]
- updateBIT(n, 3, 6);
- // Find sum after the value is updated
- System.out.println("Sum of elements in arr[0..5]"+
- " after update is " + tree.getSum(5));
- }
- }
- // Various geometric functions
- class Point{
- int x,y;
- Point(int x,int y){
- this.x=x;
- this.y=y;
- }
- }
- class Line{
- Point point1,point2;
- Line(Point point1,Point point2){
- this.point1=point1;
- this.point2=point2;
- }
- }
- public class Geometry {
- public static int direction(Line someLine,Point somePoint{
- //returns -1 if left of line, 1 if right, 0 of on line
- int D = (someLine.point2.x-someLine.point1.x)*(somePoint.y-someLine.point1.y)
- -(someLine.point2.y-someLine.point1.y)*(somePoint.x-someLine.point1.x);
- if (D>0)
- return -1;
- else if (D<0)
- return 1;
- else
- return 0;
- }
- public static double scalar(Line line1,Line line2){
- //line1 point1 = line2 point2
- int xOffset = -line1.point1.x;
- int yOffset = -line1.point1.y;
- return (line1.point2.x+xOffset)*(line2.point2.x+xOffset)
- +(line1.point2.y+yOffset)*(line2.point2.y+yOffset);
- }
- public static double cardinality(Line line){
- return Math.sqrt(Math.pow(line.point1.x-line.point2.x,2)+Math.pow(line.point1.y-line.point2.y,2));
- }
- public static double angle(Line line1,Line line2){
- //returns angle between vectors line1 and line2
- //lines are vectors which have common point!
- return Math.acos(scalar(line1,line2)/(cardinality(line1)*cardinality(line2)));
- }
- public static Point lineIntersection(Point A, Point B, Point C, Point D)
- {
- // Line AB represented as a1x + b1y = c1
- double a1 = B.y - A.y;
- double b1 = A.x - B.x;
- double c1 = a1*(A.x) + b1*(A.y);
- // Line CD represented as a2x + b2y = c2
- double a2 = D.y - C.y;
- double b2 = C.x - D.x;
- double c2 = a2*(C.x)+ b2*(C.y);
- double determinant = a1*b2 - a2*b1;
- if (determinant == 0)
- {
- // The lines are parallel. This is simplified
- // by returning a pair of FLT_MAX
- return new Point(Double.MAX_VALUE, Double.MAX_VALUE);
- }
- else
- {
- double x = (b2*c1 - b1*c2)/determinant;
- double y = (a1*c2 - a2*c1)/determinant;
- if(Math.min(A.X,B.X)<=x<=Math.max(A.X,B.X) && Math.min(A.Y,B.Y)<=y<=Math.max(A.Y,B.Y)
- && Math.min(C.X,D.X)<=x<=Math.max(C.X,D.X) && Math.min(C.Y,D.Y)<=y<=Math.max(C.Y,D.Y)) //ako lezhi presekot na dvete otsecki
- return new Point(x, y);
- else
- return new Point(Double.MAX_VALUE, Double.MAX_VALUE);
- }
- }
- //CONVEX HULL GRAHAM
- import java.awt.Point;
- import java.util.*;
- /**
- *
- */
- public final class GrahamScan {
- /**
- * An enum denoting a directional-turn between 3 points (vectors).
- */
- protected static enum Turn { CLOCKWISE, COUNTER_CLOCKWISE, COLLINEAR }
- /**
- * Returns true iff all points in <code>points</code> are collinear.
- *
- * @param points the list of points.
- * @return true iff all points in <code>points</code> are collinear.
- */
- protected static boolean areAllCollinear(List<Point> points) {
- if(points.size() < 2) {
- return true;
- }
- final Point a = points.get(0);
- final Point b = points.get(1);
- for(int i = 2; i < points.size(); i++) {
- Point c = points.get(i);
- if(getTurn(a, b, c) != Turn.COLLINEAR) {
- return false;
- }
- }
- return true;
- }
- /**
- * Returns the convex hull of the points created from <code>xs</code>
- * and <code>ys</code>. Note that the first and last point in the returned
- * <code>List<java.awt.Point></code> are the same point.
- *
- * @param xs the x coordinates.
- * @param ys the y coordinates.
- * @return the convex hull of the points created from <code>xs</code>
- * and <code>ys</code>.
- * @throws IllegalArgumentException if <code>xs</code> and <code>ys</code>
- * don't have the same size, if all points
- * are collinear or if there are less than
- * 3 unique points present.
- */
- public static List<Point> getConvexHull(int[] xs, int[] ys) throws IllegalArgumentException {
- if(xs.length != ys.length) {
- throw new IllegalArgumentException("xs and ys don't have the same size");
- }
- List<Point> points = new ArrayList<Point>();
- for(int i = 0; i < xs.length; i++) {
- points.add(new Point(xs[i], ys[i]));
- }
- return getConvexHull(points);
- }
- /**
- * Returns the convex hull of the points created from the list
- * <code>points</code>. Note that the first and last point in the
- * returned <code>List<java.awt.Point></code> are the same
- * point.
- *
- * @param points the list of points.
- * @return the convex hull of the points created from the list
- * <code>points</code>.
- * @throws IllegalArgumentException if all points are collinear or if there
- * are less than 3 unique points present.
- */
- public static List<Point> getConvexHull(List<Point> points) throws IllegalArgumentException {
- List<Point> sorted = new ArrayList<Point>(getSortedPointSet(points));
- if(sorted.size() < 3) {
- throw new IllegalArgumentException("can only create a convex hull of 3 or more unique points");
- }
- if(areAllCollinear(sorted)) {
- throw new IllegalArgumentException("cannot create a convex hull from collinear points");
- }
- Stack<Point> stack = new Stack<Point>();
- stack.push(sorted.get(0));
- stack.push(sorted.get(1));
- for (int i = 2; i < sorted.size(); i++) {
- Point head = sorted.get(i);
- Point middle = stack.pop();
- Point tail = stack.peek();
- Turn turn = getTurn(tail, middle, head);
- switch(turn) {
- case COUNTER_CLOCKWISE:
- stack.push(middle);
- stack.push(head);
- break;
- case CLOCKWISE:
- i--;
- break;
- case COLLINEAR:
- stack.push(head);
- break;
- }
- }
- // close the hull
- stack.push(sorted.get(0));
- return new ArrayList<Point>(stack);
- }
- /**
- * Returns the points with the lowest y coordinate. In case more than 1 such
- * point exists, the one with the lowest x coordinate is returned.
- *
- * @param points the list of points to return the lowest point from.
- * @return the points with the lowest y coordinate. In case more than
- * 1 such point exists, the one with the lowest x coordinate
- * is returned.
- */
- protected static Point getLowestPoint(List<Point> points) {
- Point lowest = points.get(0);
- for(int i = 1; i < points.size(); i++) {
- Point temp = points.get(i);
- if(temp.y < lowest.y || (temp.y == lowest.y && temp.x < lowest.x)) {
- lowest = temp;
- }
- }
- return lowest;
- }
- /**
- * Returns a sorted set of points from the list <code>points</code>. The
- * set of points are sorted in increasing order of the angle they and the
- * lowest point <tt>P</tt> make with the x-axis. If tow (or more) points
- * form the same angle towards <tt>P</tt>, the one closest to <tt>P</tt>
- * comes first.
- *
- * @param points the list of points to sort.
- * @return a sorted set of points from the list <code>points</code>.
- * @see GrahamScan#getLowestPoint(java.util.List)
- */
- protected static Set<Point> getSortedPointSet(List<Point> points) {
- final Point lowest = getLowestPoint(points);
- TreeSet<Point> set = new TreeSet<Point>(new Comparator<Point>() {
- @Override
- public int compare(Point a, Point b) {
- if(a == b || a.equals(b)) {
- return 0;
- }
- // use longs to guard against int-underflow
- double thetaA = Math.atan2((long)a.y - lowest.y, (long)a.x - lowest.x);
- double thetaB = Math.atan2((long)b.y - lowest.y, (long)b.x - lowest.x);
- if(thetaA < thetaB) {
- return -1;
- }
- else if(thetaA > thetaB) {
- return 1;
- }
- else {
- // collinear with the 'lowest' point, let the point closest to it come first
- // use longs to guard against int-over/underflow
- double distanceA = Math.sqrt((((long)lowest.x - a.x) * ((long)lowest.x - a.x)) +
- (((long)lowest.y - a.y) * ((long)lowest.y - a.y)));
- double distanceB = Math.sqrt((((long)lowest.x - b.x) * ((long)lowest.x - b.x)) +
- (((long)lowest.y - b.y) * ((long)lowest.y - b.y)));
- if(distanceA < distanceB) {
- return -1;
- }
- else {
- return 1;
- }
- }
- }
- });
- set.addAll(points);
- return set;
- }
- /**
- * Returns the GrahamScan#Turn formed by traversing through the
- * ordered points <code>a</code>, <code>b</code> and <code>c</code>.
- * More specifically, the cross product <tt>C</tt> between the
- * 3 points (vectors) is calculated:
- *
- * <tt>(b.x-a.x * c.y-a.y) - (b.y-a.y * c.x-a.x)</tt>
- *
- * and if <tt>C</tt> is less than 0, the turn is CLOCKWISE, if
- * <tt>C</tt> is more than 0, the turn is COUNTER_CLOCKWISE, else
- * the three points are COLLINEAR.
- *
- * @param a the starting point.
- * @param b the second point.
- * @param c the end point.
- * @return the GrahamScan#Turn formed by traversing through the
- * ordered points <code>a</code>, <code>b</code> and
- * <code>c</code>.
- */
- protected static Turn getTurn(Point a, Point b, Point c) {
- // use longs to guard against int-over/underflow
- long crossProduct = (((long)b.x - a.x) * ((long)c.y - a.y)) -
- (((long)b.y - a.y) * ((long)c.x - a.x));
- if(crossProduct > 0) {
- return Turn.COUNTER_CLOCKWISE;
- }
- else if(crossProduct < 0) {
- return Turn.CLOCKWISE;
- }
- else {
- return Turn.COLLINEAR;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement