<p>You are given an integer <code>n</code> and an integer <code>p</code> representing an array <code>arr</code> of length <code>n</code> where all elements are set to 0&#39;s, except position <code>p</code> which is set to 1. You are also given an integer array <code>banned</code> containing restricted positions. Perform the following operation on <code>arr</code>:</p>

<ul>
	<li>Reverse a <span data-keyword="subarray-nonempty"><strong>subarray</strong></span> with size <code>k</code> if the single 1 is not set to a position in <code>banned</code>.</li>
</ul>

<p>Return an integer array <code>answer</code> with <code>n</code> results where the <code>i<sup>th</sup></code> result is<em> </em>the <strong>minimum</strong> number of operations needed to bring the single 1 to position <code>i</code> in <code>arr</code>, or -1 if it is impossible.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>

<div class="example-block">
<p><strong>Input:</strong> <span class="example-io">n = 4, p = 0, banned = [1,2], k = 4</span></p>

<p><strong>Output:</strong> <span class="example-io">[0,-1,-1,1]</span></p>

<p><strong>Explanation:</strong></p>

<ul>
	<li>Initially 1 is placed at position 0 so the number of operations we need for position 0 is 0.</li>
	<li>We can never place 1 on the banned positions, so the answer for positions 1 and 2 is -1.</li>
	<li>Perform the operation of size 4 to reverse the whole array.</li>
	<li>After a single operation 1 is at position 3 so the answer for position 3 is 1.</li>
</ul>
</div>

<p><strong class="example">Example 2:</strong></p>

<div class="example-block">
<p><strong>Input:</strong> <span class="example-io">n = 5, p = 0, banned = [2,4], k = 3</span></p>

<p><strong>Output:</strong> <span class="example-io">[0,-1,-1,-1,-1]</span></p>

<p><strong>Explanation:</strong></p>

<ul>
	<li>Initially 1 is placed at position 0 so the number of operations we need for position 0 is 0.</li>
	<li>We cannot perform the operation on the subarray positions <code>[0, 2]</code> because position 2 is in banned.</li>
	<li>Because 1 cannot be set at position 2, it is impossible to set 1 at other positions in more operations.</li>
</ul>
</div>

<p><strong class="example">Example 3:</strong></p>

<div class="example-block">
<p><strong>Input:</strong> <span class="example-io">n = 4, p = 2, banned = [0,1,3], k = 1</span></p>

<p><strong>Output:</strong> <span class="example-io">[-1,-1,0,-1]</span></p>

<p><strong>Explanation:</strong></p>

<p>Perform operations of size 1 and 1 never changes its position.</p>
</div>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>1 &lt;= n &lt;= 10<sup>5</sup></code></li>
	<li><code>0 &lt;= p &lt;= n - 1</code></li>
	<li><code>0 &lt;= banned.length &lt;= n - 1</code></li>
	<li><code>0 &lt;= banned[i] &lt;= n - 1</code></li>
	<li><code>1 &lt;= k &lt;= n&nbsp;</code></li>
	<li><code>banned[i] != p</code></li>
	<li>all values in <code>banned</code>&nbsp;are <strong>unique</strong>&nbsp;</li>
</ul>

import time
from copy import deepcopy
import bisect
class Solution:
    def minReverseOperations(self, n: int, p: int, banned: List[int], k: int) -> List[int]:
        self.k=k
        self.p=p
        self.n=n
        self.list_operation = [-2] * n
        start_time = time.time()

        print("dione dfedsafs")
        list_of_result = []
        self.banned = banned
        for banned_index in self.banned:
            self.list_operation[banned_index] =-1
        if k==1:
            for index in range(0,len(self.list_operation)):
                if self.list_operation[index] ==-2:
                    self.list_operation[index] =-1
            self.list_operation[self.p] = 0
            return self.list_operation
        current = self.p
        if (current+(self.k-1))>=self.n:
            limit=(self.n-1)-current
        else:
            limit=self.k-1
        if (current-(self.k-1))<0:
            lower_limit=(self.k-1)-current
        else:
            lower_limit=0

        self.revsion_list={}
        self.list_operation[self.p] = 0  
        current_id_founded=[]
        while limit>=lower_limit:
            _end_limit=current+limit
            _start_limit=current-((self.k-1)-limit)
            if abs(_start_limit-current)<abs(_end_limit-current):
                _current = _end_limit-abs(_start_limit-current)
            else:
                _current = _start_limit+abs(_end_limit-current)
           
            limit-=1

            if self.check_and_add(1,current=_current,start_limit=_start_limit,end_limit=_end_limit):
                current_id_founded.append(_current)


        current_id_founded.sort()   
        
        operations=0
        next_leveL_founds=deepcopy(current_id_founded)
        while next_leveL_founds:
            current_id_founded = deepcopy(next_leveL_founds)
            next_leveL_founds=[]
            current_id_founded.sort()
            prev_curr_id = None
            operations += 1
            self.logger(f" for level {operations} and ids {current_id_founded}")
            while current_id_founded:
                curr_id=current_id_founded.pop()
                if abs(self.k-curr_id)<25 or abs((self.k+curr_id)-self.n)<25:
                    prev_curr_id=None
                return_next = self.check_for_operation(operations,current=curr_id,prev_limit=[prev_curr_id,None])
                self.logger(f" running founded {return_next} for  curr_id {curr_id}")
                next_leveL_founds.extend(return_next)
                
                    
                prev_curr_id = curr_id

        print(self.revsion_list)
        for index in range(0,len(self.list_operation)):
            if self.list_operation[index] ==-2:
                self.list_operation[index] =-1
        end_time = time.time()

        execution_time = end_time - start_time
        print(f"Execution time: {execution_time} seconds")
        return self.list_operation

    def logger(self,strs,allowed=False):
        if not allowed:
        
            return
        print(strs)

    def check_for_operation(self,oprations,current,prev_limit=[None,None]):
        
        if (current+(self.k-1))>=self.n:
            limit=(self.n-1)-current
        else:
            limit=self.k-1
        if (current-(self.k-1))<0:
            lower_limit=(self.k-1)-current
        else:
            lower_limit=0
        if prev_limit[0]!=None:
            gap =  (prev_limit[0]  - current)
            if prev_limit[0] > self.p > current:
                print(f" pass throth 2 {current}")
                pass
            elif self.k<gap or (self.k*1.5)>self.n:
                print(f" pass throth gap is bigger current {current} gap {gap}")
            elif current>self.p and (limit-gap)>lower_limit:
                lower_limit = limit-gap
            elif  (lower_limit+gap)<limit:
                #print(f"high limit  set to  {lower_limit+gap}")
                limit = lower_limit+gap
            self.logger(f"current {current} for gap  {gap} ")

        current_id_founded = []
        
        count_to_stop=0
        while limit>=lower_limit:
            _end_limit=current+limit
            _start_limit=current-((self.k-1)-limit)
            if abs(_start_limit-current)<abs(_end_limit-current):
                _current = _end_limit-abs(_start_limit-current)
            else:
                _current = _start_limit+abs(_end_limit-current)
            
            limit-=1
            if self.check_and_add(oprations+1,current=_current,start_limit=_start_limit,end_limit=_end_limit,pcurrent=current):
                current_id_founded.append(_current)

        current_id_founded=self.check_nearest(current,current_id_founded,current-1,oprations)
        current_id_founded=self.check_nearest(current,current_id_founded,current+1,oprations)

        self.logger(f"current {current}  dounded number {current_id_founded} ")
        
        
        current_id_founded.sort()   
        
        return current_id_founded


        
    def check_and_add(self,oprations,current,start_limit,end_limit,pcurrent=-3):
        if self.list_operation[current]==-1:
            return False
        
        if self.list_operation[current]==oprations:
            return False
        elif self.list_operation[current]>oprations or self.list_operation[current]==-2:
            

            self.list_operation[current] = oprations
            return True
        return False


        
    def get_start_and_end_valided(self,current_id,target_id):

        gap = current_id-target_id
        if abs(gap)>=self.k or gap==0:

            return [None,None]
        else:
            if gap<0:
                add=((self.k-1)-(abs(gap)))
                if add%2!=0:
                    return [None,None]
                add=add//2
                start_limit=current_id-add
                end_limit=target_id+add
            else:
                add=((self.k-1)-(abs(gap)))
                if add%2!=0:
                    return [None,None]
                add=add//2
                end_limit=current_id+add
                start_limit=target_id-add
        if  (self.n-1)<start_limit or start_limit<0 :
            self.logger(f" start end limit out of bound start_limit {start_limit} end_limit {end_limit}")
            return [None,None]
        if (self.n-1)<end_limit or end_limit<0:
            self.logger(f" start end limit out of bound start_limit {start_limit} end_limit {end_limit}")
            return [None,None]
        self.logger(f" reversed start_limit 2  {start_limit} end_limit {end_limit} add {add}")
        return [start_limit,end_limit]

    def check_nearest(self,current,current_id_founded,to_check,oprations):
        if self.k<=2:
            return current_id_founded
            
        if 0 > to_check or self.n<=to_check:
            return current_id_founded
        oprs= self.list_operation[to_check]
        
        if oprs<=(oprations+1) and oprs!=-2:
            return current_id_founded

        if to_check not  in current_id_founded:
            _current=to_check
            res=self.get_start_and_end_valided(current,_current)
            if res[0]!=None:
                if self.check_and_add(oprations+1,current=_current,start_limit=res[0],end_limit=res[1],pcurrent=current):
                    current_id_founded.append(_current)
        return current_id_founded
        
33100