import java.io.PrintStream; import java.util.ArrayDeque; import java.util.Arrays; import java.util.Queue; import java.util.Scanner; /** * Solution to Zoning Houses * * @author vanb */ public class zoning_vanb { private static Scanner sc; private static PrintStream ps; /** Array of X coordinates */ public long xs[]; /** Array of Y coordinates */ public long ys[]; /** * An interface for a generic node of a Segment Tree * * @author vanb */ public interface SegmentTreeValue { /** * Merge two nodes * * @param other The other node * @return A merged node */ public SegmentTreeValue merge( SegmentTreeValue other ); } /** * This is the value of a node of the segments tree. * It will contain the minimum and maximum X and Y, and the * second minimum and maximum X and Y, for every house in its segment. * * @author vanb * */ public class Limits implements SegmentTreeValue { /** House numbers for Maximums and minimums */ public int maxx, maxy, minx, miny; /** House numbers for Penultimate maxs and mins */ public int nextmaxx, nextmaxy, nextminx, nextminy; /** * Create a node for House i * * @param i INdex of a House */ public Limits( int i ) { // The max and min indices are just i maxx = maxy = minx = miny = i; // There's only one house, so there are no nexts nextmaxx = nextmaxy = -1; nextminx = nextminy = -1; } /** * Produce a pretty String for debugging. */ public String toString() { String pretty = "[ "; pretty += "maxx=" + maxx + " (" + xs[maxx] + ") "; pretty += "nextmaxx=" + nextmaxx + " (" + (nextmaxx<0?"?":xs[nextmaxx]) + ") "; pretty += "minx=" + minx + " (" + xs[minx] + ") "; pretty += "nextminx=" + nextminx + " (" + (nextminx<0?"?":xs[nextminx]) + ") "; pretty += "maxy=" + maxy + " (" + ys[maxy] + ") "; pretty += "nextmaxy=" + nextmaxy + " (" + (nextmaxy<0?"?":ys[nextmaxy]) + ") "; pretty += "miny=" + miny + " (" + ys[miny] + ") "; pretty += "nextminy=" + nextminy + " (" + (nextminy<0?"?":ys[nextminy]) + ") "; pretty += "]"; return pretty; } /** This array will be useful for finding the top 2 */ private int tops[] = new int[2]; /** * Add an element, see if it's in the top 2. * * @param i Index of element to add * @param v Array of X or Y coordinate values * @param max true if seeking maxs, false for mins */ private void addTop( int i, long v[], boolean max ) { if( i>=0 ) { if( tops[0]==-1 || (max && v[i]>v[tops[0]]) || (!max && v[i]v[tops[1]]) || (!max && v[i] { /** The number of elements */ public int size; /** The tree itself */ public T tree[]; /** * Create a Segment Tree for a segment with 'size' elements. * * @param size Number of elements */ public SegmentTree( int size ) { this.size = size; // If there are n elements, then the number of leaves // in the Segment Tree could be up to k, where k is the smallest // power of 2 greater than or equal to n. int k = Integer.highestOneBit( size ); if( k!=size ) k<<=1; // A binary tree with k leaves will have k-1 internal nodes. // So, we need k+k-1 overall. But, we start at 1, not 0, so // we need one more, since there's one (at 0) we won't use. tree = (T[]) new SegmentTreeValue[k + k]; // We're use null as a flag that a value hasn't been set here. Arrays.fill( tree, null ); } /** * Put a value over an interval into the Segment tree. * This is an internal method. * * @param node Index of the current node * @param lo Low index of the segment for this node * @param hi High index of the segment for this node * @param lower Lower bound of the interval of interest * @param upper Upper bound of the interval of interest * @param value Value to fill in the interval [lower,upper] */ private T put( int node, int lo, int hi, int lower, int upper, T value ) { if( lower<=lo && hi<=upper ) { tree[node] = value; } else { // Build left and right subtrees int mid = (hi+lo)/2; T left=null, right=null; if( lower<=mid ) left = put( node+node, lo, mid, lower, upper, value ); if( upper>mid ) right = put( node+node+1, mid+1, hi, lower, upper, value ); tree[node] = merge( tree[node], merge( left, right ) ); } return tree[node]; } /** * Put a value over an interval into the Segment tree. * This is an outward facing method. * * @param lower Lower bound of the interval of interest * @param upper Upper bound of the interval of interest * @param value Value to fill in the interval [lower,upper] */ public void put( int lower, int upper, T value ) { put( 1, 0, size-1, lower, upper, value ); } /** * Safely merge two nodes. * This uses the objects' merge, but protects against nulls. * * @param a A node * @param b Another node * @return The merging of a and b */ private T merge( T a, T b ) { T result = null; if( a!=null && b!=null ) result = (T)a.merge( b ); else if( a!=null ) result = a; else if( b!=null ) result = b; return result; } /** * Get a value from the Segment Tree. * This is an internal method. * * @param node Index of the current node * @param lo Low index of the segment for this node * @param hi High index of the segment for this node * @param lower Low index of the segment we want to get the value from * @param upper High index of the segment we want to get the value from * @return */ private T get( int node, int lo, int hi, int lower, int upper ) { T result = null; if( nodemid ) right = get( node+node+1, mid+1, hi, lower, upper ); result = merge( left, right ); } } return result; } /** * Get a value from the Segment Tree. * This is an outward facing method. * * @param lower Low index of the segment we want to get the value from * @param upper High index of the segment we want to get the value from * @return A node for this segment */ public T get( int lower, int upper ) { return get( 1, 0, size-1, lower, upper ); } } /** * Do it! */ private void doit() { int n = sc.nextInt(); int q = sc.nextInt(); SegmentTree limits = new SegmentTree(n); xs = new long[n]; ys = new long[n]; // Read in the house locations, // put them in the segment tree. for( int i=0; i0 ) { // We'll translate from 1-based to 0-based int a = sc.nextInt()-1; int b = sc.nextInt()-1; // Get the limits of this segment Limits l = (Limits)limits.get( a, b ); // Omit each of the maximums, see what we get. long side = l.omit( l.maxx ); side = Math.min( side, l.omit( l.minx ) ); side = Math.min( side, l.omit( l.maxy ) ); side = Math.min( side, l.omit( l.miny ) ); ps.println( side ); } } /** * main * * @param args * @throws Exception */ public static void main( String[] args ) throws Exception { sc = new Scanner( System.in ); ps = System.out; new zoning_vanb().doit(); } }