iez's blog

By iez, history, 10 months ago, In English

You are given an array of n numbers

Find the longest consecutive subarray so that The Last and First member of the sub array is Neither the Smallest or the Biggest member of That subarray (not the entire array)

for example

1 3 2 4 6 5 7

the sub array [3, 2, 4, 6, 5]

in this subarray the smallest member is 2 and the biggest member is 6, the first member is 3 which is not equal to 2 or 6, the last member 5 is not equal to 2 or 6 either so this is a valid subarray, so you cout 2 6 (the l and r of the subarray)

The goal is to find a Valid subarray

the second Goal is to find the Biggest valid subarray

the numbers are from 0 up to 1e9 and n is from from 1 up to 2*1e5

My strategy is to make a two vector of vectors, saving the numbers sorted from index 0 up to i so you can always know the smallest and biggest member of each subarray and then just do a sliding window algorithm.

  • Vote: I like it
  • +12
  • Vote: I do not like it

»
10 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

Auto comment: topic has been updated by iez (previous revision, new revision, compare).

»
10 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

I believe this problem can be directly solved by removing either the minimum or maximum element from both ends of the array.

»
10 months ago, hide # |
Rev. 2  
Vote: I like it 0 Vote: I do not like it

I think you could use a multi_set to store all the value from the array, and remove either value from both end if is the min or max val from the subarray/subsequence.

Repeat until it's valid. The time complexity is O(nlogn):D

  • »
    »
    10 months ago, hide # ^ |
     
    Vote: I like it 0 Vote: I do not like it

    My personal though process:

    1. If we trimmed an element which is not the min_val nor the max_val from the subarray, then nothing will happened except the length of the subarray decrease by 1 -> bad bad:D
    2. If we trimmed an element which is local min/max val from the subarray that on the right/left end of the array, we won't lose any valid solution.

    And i also think that this could also work with an subsequence from the array, cause:

    1. If we remove an min/max val in the middle of the subsequence(not the right/left end), it won't change an invalid subsequence into a valid subsequence cause the right/left end remain the same.

    So it's still a bad thing to remove element from middle of the subsequence. I think this will work, correct me if i'm wrong pls:D

    • »
      »
      »
      10 months ago, hide # ^ |
       
      Vote: I like it 0 Vote: I do not like it

      I think your solution works and yes, it also works for the problem of finding the longest subsequence under the same conditions.

    • »
      »
      »
      10 months ago, hide # ^ |
       
      Vote: I like it 0 Vote: I do not like it

      Also, I think the time complexity can be reduced to O(n) using your algorithm if we use a min priority queue and a max priority queue to find the next min and max elements after we remove an element instead of a multiset.

      • »
        »
        »
        »
        10 months ago, hide # ^ |
         
        Vote: I like it 0 Vote: I do not like it

        I think the priority queue not gonna make it O(n) casuse on 1 operation, an priority queue takes O(logn) to compute.

        The valid O(n) solution might be using 4 monotonic stack for next/previous min/max(precompute in O(n) and remove element from both end like usual. But it's an absurd amount of coding for a problem with constrain n < 2e5. Maybe if is was limit on number of steps you can take, or the time constrain need strictly O(kn) with k <= 10 and n is large enough. I'll use this method.

        Personaly, i'll stick with using multi_set because it will make my code shorter, easier to code and understand.

  • »
    »
    10 months ago, hide # ^ |
     
    Vote: I like it 0 Vote: I do not like it

    My submission 325661310 might be valid with this problem, cause this code AC with the same problem with the same constrain(1793C - Dora and Search)

»
10 months ago, hide # |
Rev. 7  
Vote: I like it 0 Vote: I do not like it

For the above question, I have the following algorithm:

1. Find maximum of the array
2. Find minimum of the array
3. Let index of leftmost element that isnt the maximum or minimum be l
4. Let index rightmost element that isnt the maximum or minimum be r
5. Output l and r if l < r, else output "No such subarray"
Why this works? (For both questions)
1. Case where there isnt such a valid subarray: 
There are only a few cases where there wont exist such a valid subarray: case where the array has exactly 1 or 2 distinct elements and arrays of length 3 with only three distinct elements. It is easy to see why these fail. In these cases either l == r or l > r.
2. Case where there is such a vaild subarray:
By construction, we definitely get a valid subarray. To prove that this is the biggest, assume a bigger subarray B, and call our constructed subarray with l and r as C.
 
Case 2.1: Suppose B is to the left of C
    Then the leftmost element of B is the actual leftmost element which our algorithm will find. So Leftmost element of B is the leftmost element of C. 
Case 2.2: Similarly, suppose B is to the right of C and a similar claim can now be made with the rightmost element of B and C
    So, there is a contradiction in our assumption that B is arger than C i.e it is NOT the case that B is larger than C.
Hence proved, by contradiction that C is the largest such subarray.

Time complexity:
one array pass each for steps 1-2;
Tow array passes each for steps 3-4;
o(1) printing for step 5;
total: o(n);

EDIT: Formatting changes, Corrected steps 3 and 4 and their time complexities

EDIT 2: Added c++ code

Code
  • »
    »
    10 months ago, hide # ^ |
     
    Vote: I like it 0 Vote: I do not like it

    I think your algorithm would work if the question was "Find the longest consecutive subarray so that The Last and First member of the sub array is Neither the Smallest nor the Biggest member of the entire array".

    However, the question is "Find the longest consecutive subarray so that The Last and First member of the sub array is Neither the Smallest or the Biggest member of That subarray (_not the entire array_)".

    • »
      »
      »
      10 months ago, hide # ^ |
       
      Vote: I like it 0 Vote: I do not like it

      Hmm, you are right. The subarray itself might have its ends containing its own largest and smallest elements. Thanks, the algorithm is wrong.

»
10 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

Maybe these solutions would work? (First problem: Find a valid subarray (It doesn't have to be the biggest), which means a subbaray of size 1 should be valid, because the last and first element is neither the max or min element of the original array

void solve() {
  int n; cin >> n;
  vector<int> a(n);
  for(int i = 0;i < n;i++) cin >> a[i];
  int minn = *min_element(all(a)), maxx = *max_element(all(a));
  
  for(int i = 0;i < n;i++){
    if(a[i] != minn && a[i] != maxx){cout << a[i]; return;}
  }
  cout << -1;
}

For problem 2 I don't think I'm capable yet.. I have an idea using queues but I'll update soon when I figure it out

»
10 months ago, hide # |
Rev. 2  
Vote: I like it 0 Vote: I do not like it

If someone has an easier approach, please share. I think we can do d&c. Suppose we split a segment in the middle, and the "optimal" segment lies over this split. Then it consists of a suffix of the left segment, and a prefix of the right segment. We have 2 cases:

  • One of the endpoints (left or right) is neither the smallest nor the largest element of the corresponding half.

  • The endpoints are the largest (but not smallest) and the smallest (but not largest) in their halfs.

For the first case, we iterate over the other side, and we only need to check the furthest prefix/suffix on the other side that satisfies the first case.

For the second case, we can do 2 pointers approach over the suffixes/prefixes that satisfy this case, and keep track of the furthest suffix/prefix that is still (maybe) possible. For example, if right endpoint is minimum in its half, and left endpoint is maximum, and H is the largest value in the right half, then from the suffix maxima on the left side, we point to the largest one that is strictly less than H. Then we need to check whether the minimum on the left side is less than the right endpoint.

This is O(n log(n)). I feel like there might be a way easier solution, so please tell me if so.

  • »
    »
    10 months ago, hide # ^ |
     
    Vote: I like it +8 Vote: I do not like it

    First choose all elements. If one endpoint is the smallest or the largest element, then we cannot let it is not by moving another endpoint. Then we can only remove this endpoint. Repeating this procedure is OK.

»
10 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

This problem is basically the same as 1793C - Dora and Search

  • »
    »
    10 months ago, hide # ^ |
     
    Vote: I like it 0 Vote: I do not like it

    But in this problem it is not mentioned that the numbers are permutaions of n, it can be any random n numbers.

    • »
      »
      »
      10 months ago, hide # ^ |
       
      Vote: I like it 0 Vote: I do not like it

      I think original solution approach should still work even if they're not permutations, though might not be able to work in $$$O(n)$$$

      • »
        »
        »
        »
        10 months ago, hide # ^ |
         
        Vote: I like it 0 Vote: I do not like it

        Ah no see the problem is in dora and the search its a permutation

        if either corner is mn or mx you can just ++ or -- the mx or min to find the Next mx or min

        because if till the current index the mx stayed valid and now it falls of the l, we can mx++ because we can prove the new max is to the right of the array, so all we got to do is also check if for our R its also still to the right of the array, no need to Loop to see what is the min or max to the right

        best case for this question is n(log n) because n is not possible

        • »
          »
          »
          »
          »
          10 months ago, hide # ^ |
           
          Vote: I like it 0 Vote: I do not like it

          There’s not much difference, the core idea is same, it’s just the way we maintain the min and max in the subarray is different(like multiset)

          • »
            »
            »
            »
            »
            »
            10 months ago, hide # ^ |
             
            Vote: I like it 0 Vote: I do not like it

            ye but the way you save min and max can go up to n^2, i was looking for the best one which rn is n log n

    • »
      »
      »
      10 months ago, hide # ^ |
      Rev. 2  
      Vote: I like it 0 Vote: I do not like it

      Why bother solving it, just cheat it Saar, like you do in contests

»
10 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

the difficulty of this problem could change depending on whether the array is a permutation or not. A permutation is a more friendly one

»
10 months ago, hide # |
Rev. 3  
Vote: I like it 0 Vote: I do not like it

First let's keep an array that holds the biggest index such that there exists two indices R[k]: a[i] > a[j] and k <= i < j, or -1 if no index exists, then we can also keep an array that finds the smallest index such that a[i] > a[j] and i < j, or -1 if no index exists, let's call these arrays R and L respectively, then a valid array exists if L[i] < R[i] and L[i] != -1, and the biggest one will be when the R[i] — L[i] is at a maximum, let me demonstrate with your input: 1. idx= 0 1 2 3 4 5 6 2. A = 1 3 2 4 6 5 7 3. L = -1 2 -1 -1 5 -1 -1 4. R = 5 5 5 5 5 -1 -1 from this we can see that the only valid subarray is from [1, 5], since R[1] = 5 > L[1] = 2, and L[1] != -1. Is this approach correct?

  • »
    »
    10 months ago, hide # ^ |
     
    Vote: I like it 0 Vote: I do not like it
    import java.util.*;
    public class nicequestion {
        public static void main(String[] args) {
            Scanner sc=new Scanner(System.in);
            int n=sc.nextInt();
            while(n-->0) {
                int a=sc.nextInt();
                int[]arr=new int[a];
                for(int i=0;i<a;i++){
                    arr[i]=sc.nextInt();
                }
                int l=0;
                int r=a-1;
                boolean isFound=false;
                int L=1;
                int R=a;
                while(l<=r){
                    if(arr[l]==L){
                         l++;
                         L++;
                         continue;
                    }if(arr[l]==R){
                        l++;
                        R--;
                        continue;
                    }if(arr[r]==L){
                         L++;
                         r--;
                         continue;
                    }
                    if(arr[r]==R){
                        r--;
                        R--;
                        continue;
                    }else{
                         isFound=true;
                        break;
                    }
                    // System.out.println(l+1+ " "+ r+1);
                   
    
                }
                if(!isFound){
                    System.out.println(-1);
                }else{
                    System.out.println((l+1)+" "+(r+1));
                }
            }
        }
    }  
    

    See the java Code it is accepted....

    What I did was 1.Take l and r as 0 and n-1 2.Take L and R as 1 and n; 3.I want to see if (a[l]==L or a[l]==R) or (a[r]==L or a[r]==R) 4.According to that I incremented or decremented the values of L and R, l, r

»
10 months ago, hide # |
 
Vote: I like it +1 Vote: I do not like it

Nice problem btw