lintcode 346 · Interval extreme value XOR [hard monotonic stack XOR operation]

Title

https://www.lintcode.com/problem/346

Given an array, please calculate the XOR of the maximum value or the minimum value of all subintervals.



The specific steps are:
First, for a subrange, find the maximum and minimum values of the range, and then XOR these two numbers, you can get a value.
Second, find all the subranges of this array, XOR the resulting values, and you'll get the correct solution.
1 <= n <= 1e6
1 <= a[i] <= 1e6

Sample
Example 1:

Input: [1, 2, 3]
Output: 0
illustrate: 
This array has 6 subranges: [1], [2], [3], [1, 2], [2, 3], [1, 2, 3]
The corresponding XOR sums are: 0, 0, 0, 3, 1, 2
The final answer is: 0
Example 2:

Input: [1, 3, 2]
Output: 1
illustrate: 
This array has 6 subranges: [1], [3], [2], [1, 3], [3, 2], [1, 3, 2]
The corresponding XOR sums are: 0, 0, 0, 2, 1, 2
The final answer is: 1

Prerequisite knowledge

Monotone stack, or operation

Answer

public class Solution {<!-- -->
    /**
     * @param nums: a list of integers
     * @return: The xorsum of maximun value xor minimun value of all subintervals
     */
    public int xorSum(int[] nums) {<!-- -->
            //monotone stack
        int n = nums.length;
        int[] lmin = new int[n], lmax = new int[n], rmin = new int[n], rmax = new int[n];
        Stack<Integer> stacklmin = new Stack<>(), stacklmax = new Stack<>(),
                stackrmin = new Stack<>(), stackrmax = new Stack<>();

        for (int i = 0; i <n ; i + + ) {<!-- -->
            while (!stacklmin.isEmpty() & amp; & amp; nums[i] > nums[stacklmin.peek()])
                stacklmin.pop();
            lmin[i]= (stacklmin.isEmpty())?i:i-stacklmin.peek()-1;
            stacklmin.add(i);

            while (!stacklmax.isEmpty() & amp; & amp; nums[i]< nums[stacklmax.peek()])
                stacklmax.pop();
            lmax[i] = (stacklmax.isEmpty())?i: i-stacklmax.peek()-1;
            stacklmax.add(i);

            int ri = n-i-1;

            while (!stackrmin.isEmpty() & amp; & amp; nums[ri] >= nums[stackrmin.peek()])
                stackrmin.pop();
            rmin[ri] = (stackrmin.isEmpty())? n-ri-1: stackrmin.peek()-ri-1;
            stackrmin.add(ri);

            while (!stackrmax.isEmpty() & amp; & amp; nums[ri] <= nums[stackrmax.peek()])
                stackrmax.pop();
            rmax[ri] = (stackrmax.isEmpty())? n-ri-1: stackrmax.peek()-ri-1;
            stackrmax.add(ri);
        }

        int ans =0;
        for (int i = 0; i < n; i + + ) {<!-- -->
            int cnt = lmin[i] + rmin[i] + 2;
            cnt + = (lmin[i]%2)*(rmin[i]%2);
            cnt + = lmax[i] + rmax[i] + 2;
            cnt + =(lmax[i]%2)*(rmax[i]%2);
            ans^=(cnt%2)*nums[i];
        }
        return ans;
    }
}

Local test code

public class LC966 {<!-- -->


    public static double getClosestDistance(double[] x, double[] y) {<!-- -->
        //Note: This problem cannot be solved with violence. You can use the divide and conquer strategy.
        int n = x.length;
        List<Info> points = new ArrayList<>();
        for (int i = 0; i < n; i + + ) {<!-- -->
            points.add(new Info(x[i], y[i]));
        }

        Collections.sort(points, (a, b) -> {<!-- -->
            if (a.x == b.x) return 0;
            if (a.x > b.x) return 1;
            return -1;
        });

        return nearestPair(points, 0, n - 1);
    }

    // Calculate the distance between the nearest point pairs in the two-dimensional plane point set
    // The x coordinate interval is [p[l],p[r]]
    //Input: search interval
    // Output: distance of the nearest point pair
    public static double nearestPair(List<Info> ps, int l, int r) {<!-- -->
        //Process the smallest subproblem
        int n = r - l + 1;
        if (n <= 3) {<!-- -->
            return f(ps, l, r);
        }


        //Handle general problems and divide sub-intervals
        int mid = (l + r) / 2;
        Info mp = ps.get(mid);
        double d1 = nearestPair(ps, l, mid);
        double d2 = nearestPair(ps, mid + 1, r);
        //Merge the problem and separate out a sub-interval with a width of 2d
        double d = Math.min(d1, d2);

        List<Info> strip = new ArrayList<>();
        for (int i = l; i <= r; i + + ) {<!-- -->
            Info cur = ps.get(i);
            if (Math.abs(cur.x - mp.x) < d)
                strip.add(cur);
        }

        Collections.sort(strip, (a, b) -> {<!-- -->
            if (a.y == b.y) return 0;
            if (a.y > b.y) return 1;
            return -1;
        });

        return f2(strip, d);
    }

    public static double f(List<Info> ps, int l, int r) {<!-- -->
        int n = r - l + 1;
        double min = Double.MAX_VALUE;
        for (int i = 0; i < n; i + + ) {<!-- -->
            for (int j = i + 1; j < n; j + + ) {<!-- -->
                double cur = dis(ps.get(l + i), ps.get(l + j));
                if (cur < min) min = cur;
            }
        }
        return min;
    }

    public static double f2(List<Info> strip, double d) {<!-- -->
        int n = strip.size();
        double min = d;
        for (int i = 0; i < n; i + + ) {<!-- -->
            Info a = strip.get(i);
            for (int j = i + 1; j < n; j + + ) {<!-- -->
                Info b = strip.get(j);
                if (b.y - a.y >= d) break;

                min = Math.min(min, dis(a, b));
            }
        }
        return min;
    }

    public static double dis(Info a, Info b) {<!-- -->
        return Math.sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
    }

    static class Info {<!-- -->
        double x;
        double y;

        public Info(double x, double y) {<!-- -->
            this.x = x;
            this.y = y;
        }
    }

    public static void main(String[] args) {<!-- -->
        double[] x = {<!-- -->1.0, 2.0, 3.0, 4.0, 5.0},
                y = {<!-- -->2.0, 3.0, 1.0, 2.0, 2.0},
                x1 = {<!-- -->1.0, 2.0, 3.0, 4.0, 5.0},
                y1 = {<!-- -->2.0, 3.0, 1.0, 2.0, 7.0};

        System.out.println(getClosestDistance(x, y)); // 1.00
      // System.out.println("Answer:" + new Solution().getClosestDistance(x, y)); // 1.00
        System.out.println(getClosestDistance(x1, y1)); // 1.41
       // System.out.println("Answer:" + new Solution().getClosestDistance(x1, y1)); // 1.41
    }
   }