Costly Intervals


Problem Statement :


Given an array, your goal is to find, for each element, the largest subarray containing it whose cost is at least k.

Specifically, let A = [A1, A2, . . . , An ]  be an array of length n, and let  be the subarray from index  l to index r. Also,

Let MAX( l, r ) be the largest number in Al. . . r.
Let  MIN( l, r ) be the smallest number in Al . . .r .
Let OR( l , r )  be the bitwise OR of the elements of Al. . .r.
Let AND( l , r ) be the bitwise AND of the elements of Al. . .r.
The cost of Al . . .r , denoted cost( l, r ), is defined as

The size of Al . . .r is defined as r - l +1.
You are given the array  and and an integer . For each index  from  to , your goal is to find the largest size of any subarray  such that  and .

Complete the function costlyIntervals which takes two integers n and k as first line of input, and array  A1, A2, . . . , An in the second line of input. Return an array of n integers, where the ith element contains the answer for index i of the input array, 1 <= i <= n. Every element of the output array denotes the largest size of a subarray containing i whose cost is at least k, or -1 if there is no such subarray.



Solution :



title-img


                            Solution in C :

In C++ :






#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int Inf = 1000000007;
const int Maxn = 100005;
const int Maxm = 20;
const int Maxb = 31;

int n, k;
int a[Maxn];
int mx[Maxn][Maxm], mn[Maxn][Maxm];
int nxt[Maxn][Maxb][2];
int res[Maxn];
vector <int> add[Maxn], rem[Maxn];
map <int, int> M;

int Get(int ind, int forb, int &Mn, int &Mx, int cur)
{
    int pnt = ind;
    for (int i = Maxm - 1; i >= 0; i--)
        if (pnt + (1 << i) <= forb) {
            int candmx = max(Mx, mx[pnt][i]);
            int candmn = min(Mn, mn[pnt][i]);
            if (ll(cur) - ll(candmx - candmn) >= k) {
                Mx = candmx; Mn = candmn;
                pnt += 1 << i;
            }
        }
    int res = pnt;
    for (int i = Maxm - 1; i >= 0; i--)
        if (pnt + (1 << i) <= forb) {
            Mx = max(Mx, mx[pnt][i]);
            Mn = min(Mn, mn[pnt][i]);
            pnt += 1 << i;
        }
    return res;
}

int main() {
    scanf("%d %d", &n, &k);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
        mx[i][0] = mn[i][0] = a[i];   
    }
    for (int j = 1; j < Maxm; j++)
        for (int i = 1; i + (1 << j) <= n + 1; i++) {
            int nxt = i + (1 << j - 1);
            mx[i][j] = max(mx[i][j - 1], mx[nxt][j - 1]);
            mn[i][j] = min(mn[i][j - 1], mn[nxt][j - 1]);
        }
    for (int i = 0; i < Maxb; i++)
        nxt[n + 1][i][0] = nxt[n + 1][i][1] = n + 1;
    for (int i = n; i > 0; i--)
        for (int j = 0; j < Maxb; j++)
            for (int k = 0; k < 2; k++)
                if (bool(a[i] & 1 << j) == k) nxt[i][j][k] = i;
                else nxt[i][j][k] = nxt[i + 1][j][k];
    for (int i = 1; i <= n; i++) {
        int Or = a[i], And = a[i];
        int Mn = Inf, Mx = -Inf;
        int st = i;
        while (st <= n) {
            int lim = n + 1;
            for (int j = 0; j < Maxb; j++) {
                if (!(Or & 1 << j)) lim = min(lim, nxt[st + 1][j][1]);
                if (And & 1 << j) lim = min(lim, nxt[st + 1][j][0]);
            }
            int got = Get(st, lim, Mn, Mx, Or - And);
            if (got > st) {
                int cand = got - i;
                add[i].push_back(cand); rem[got].push_back(cand);
            }
            for (int j = 0; j < Maxb; j++) {
                if (!(Or & 1 << j) && lim == nxt[st + 1][j][1]) Or |= 1 << j;
                if (bool(And & 1 << j) && lim == nxt[st + 1][j][0]) And ^= 1 << j;
            }
            st = lim;
        }
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 0; j < add[i].size(); j++)
            M[add[i][j]]++;
        for (int j = 0; j < rem[i].size(); j++)
            if (--M[rem[i][j]] == 0) M.erase(rem[i][j]);
        if (!M.empty()) {
            map <int, int>::iterator it = M.end(); it--;
            printf("%d\n", it->first);
        } else printf("-1\n");
    }
    return 0;
}








In Java :





import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Comparator;
import java.util.InputMismatchException;
import java.util.TreeSet;

public class D2 {
    InputStream is;
    PrintWriter out;
    String INPUT = "";
    
    void solve()
    {
        int n = ni(), K = ni();
        int[] a = na(n);
        
        int[] ra = new int[n];
        for(int i = 0;i < n;i++)ra[i] = -a[i];
        
        int[][] stmin = build(a);
        int[][] stmax = build(ra);
        
        int[][] efs = new int[80*n][];
        int efp = 0;
        int esp = 0;
        
        int[][] oas = new int[0][];
        for(int i = n-1;i >= 0;i--){
            int[][] noas = new int[40][];
            int p = 0;
            for(int j = 0;j < oas.length;j++){
                oas[j][0] |= a[i];
                oas[j][1] &= a[i];
                if(p > 0 && noas[p-1][0] == oas[j][0] && 
                        noas[p-1][1] == oas[j][1]){
                    noas[p-1][2] = oas[j][2];
                }else{
                    noas[p++] = oas[j];
                }
            }
            if(!(p > 0 && noas[p-1][0] == a[i] && 
                    noas[p-1][1] == a[i])){
                noas[p++] = new int[]{a[i], a[i], i};
            }else{
                noas[p-1][2] = i;
            }
            oas = Arrays.copyOf(noas, p);
            
//            tr(i, oas);
            
            int to = n;
            for(int[] oa : oas){
                // [oa[2], to)
                int cha = oa[0] - oa[1];
                int low = oa[2]-1, high = to;
                while(high - low > 1){
                    int h = high+low>>1;
                    // [i,h]
//                    tr(h, oa, to, cha, -rmq(stmax, i, h+1) - rmq(stmin, i, h+1));
                    if(cha - (-rmq(stmax, i, h+1) - rmq(stmin, i, h+1)) >= K){
                        low = h;
                    }else{
                        high = h;
                    }
                }
                if(low >= oa[2]){
//                    tr(i, oa, to, low);
                    efs[efp++] = new int[]{i, low - i + 1, i};
                    efs[efp++] = new int[]{low+1, low - i + 1, i};
                }
                to = oa[2];
            }
        }
        
        int I = -1;
        int[] anss = new int[n];
        Arrays.fill(anss, I);
        
        Arrays.sort(efs, 0, efp, new Comparator<int[]>() {
            public int compare(int[] a, int[] b) {
                return a[0] - b[0];
            }
        });
        TreeSet<Long> set = new TreeSet<Long>();
        
        int q = 0;
        for(int i = 0;i < n;i++){
            while(q < efp && efs[q][0] <= i){
                long code = (long)efs[q][1]<<32|efs[q][2];
                if(set.contains(code)){
                    set.remove(code);
                }else{
                    set.add(code);
                }
                q++;
            }
            if(!set.isEmpty()){
                Long first = set.last();
                anss[i] = Math.max(anss[i], (int)(first>>>32));
            }
        }
        
        for(int v : anss){
            out.println(v);
        }
    }
    
    public static int[][] build(int[] a)
    {
        int n = a.length;
        int b = 32-Integer.numberOfLeadingZeros(n);
        int[][] ret = new int[b][];
        for(int i = 0, l = 1;i < b;i++, l*=2) {
            if(i == 0) {
                ret[i] = a;
            }else {
                ret[i] = new int[n-l+1];
                for(int j = 0;j < n-l+1;j++) {
                    ret[i][j] = Math.min(ret[i-1][j], ret[i-1][j+l/2]);
                }
            }
        }
        return ret;
    }
    
    // [a,b)
    public static int rmq(int[][] or, int l, int r)
    {
        assert l <= r;
        if(l >= r)return Integer.MAX_VALUE;
        // 1:0, 2:1, 3:1, 4:2, 5:2, 6:2, 7:2, 8:3
        int t = 31-Integer.numberOfLeadingZeros(r-l);
        return Math.min(or[t][l], or[t][r-(1<<t)]);
    }

    
    void run() throws Exception
    {
        is = INPUT.isEmpty() ? System.in : new ByteArrayInputStream(INPUT.getBytes());
        out = new PrintWriter(System.out);
        
        long s = System.currentTimeMillis();
        solve();
        out.flush();
        if(!INPUT.isEmpty())tr(System.currentTimeMillis()-s+"ms");
    }
    
    public static void main(String[] args) throws Exception { new D2().run(); }
    
    private byte[] inbuf = new byte[1024];
    public int lenbuf = 0, ptrbuf = 0;
    
    private int readByte()
    {
        if(lenbuf == -1)throw new InputMismatchException();
        if(ptrbuf >= lenbuf){
            ptrbuf = 0;
            try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); }
            if(lenbuf <= 0)return -1;
        }
        return inbuf[ptrbuf++];
    }
    
    private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); }
    private int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }
    
    private double nd() { return Double.parseDouble(ns()); }
    private char nc() { return (char)skip(); }
    
    private String ns()
    {
        int b = skip();
        StringBuilder sb = new StringBuilder();
        while(!(isSpaceChar(b))){ // when nextLine, (isSpaceChar(b) && b != ' ')
            sb.appendCodePoint(b);
            b = readByte();
        }
        return sb.toString();
    }
    
    private char[] ns(int n)
    {
        char[] buf = new char[n];
        int b = skip(), p = 0;
        while(p < n && !(isSpaceChar(b))){
            buf[p++] = (char)b;
            b = readByte();
        }
        return n == p ? buf : Arrays.copyOf(buf, p);
    }
    
    private char[][] nm(int n, int m)
    {
        char[][] map = new char[n][];
        for(int i = 0;i < n;i++)map[i] = ns(m);
        return map;
    }
    
    private int[] na(int n)
    {
        int[] a = new int[n];
        for(int i = 0;i < n;i++)a[i] = ni();
        return a;
    }
    
    private int ni()
    {
        int num = 0, b;
        boolean minus = false;
        while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
        if(b == '-'){
            minus = true;
            b = readByte();
        }
        
        while(true){
            if(b >= '0' && b <= '9'){
                num = num * 10 + (b - '0');
            }else{
                return minus ? -num : num;
            }
            b = readByte();
        }
    }
    
    private long nl()
    {
        long num = 0;
        int b;
        boolean minus = false;
        while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
        if(b == '-'){
            minus = true;
            b = readByte();
        }
        
        while(true){
            if(b >= '0' && b <= '9'){
                num = num * 10 + (b - '0');
            }else{
                return minus ? -num : num;
            }
            b = readByte();
        }
    }
    
    private static void tr(Object... o) { System.out.println(Arrays.deepToString(o)); }
}








In C :






#include <stdio.h>
#include <stdlib.h>
#define INF 200000
int get(int l,int r);
int max(int x,int y);
int min(int x,int y);
void init( int n );
void range_increment( int i, int j, int val );
int query( int i );
void sort_a(int*a,int size,int*new_size);
void merge(int*a,int*left,int*right,int left_size, int right_size,int*new_size);
int N,a[100000],b[100000],map[100001],dp[4][100000][18],dp1[30][100000],dp2[30][100000],tree[400000];

int main(){
  int n,k,s,ns,h,l,m,i,j;
  scanf("%d%d",&n,&k);
  for(i=j=1,map[0]=0;i<=100000;i++)
    if(j*2<=i){
      j*=2;
      map[i]=map[i-1]+1;
    }
    else
      map[i]=map[i-1];
  for(i=0;i<n;i++)
    scanf("%d",a+i);
  for(i=0;i<n;i++)
    dp[0][i][0]=dp[1][i][0]=dp[2][i][0]=dp[3][i][0]=a[i];
  for(j=1;1<<j<=n;j++)
    for(i=0;i+(1<<j)-1<n;i++){
      dp[0][i][j]=max(dp[0][i][j-1],dp[0][i+(1<<(j-1))][j-1]);
      dp[1][i][j]=min(dp[1][i][j-1],dp[1][i+(1<<(j-1))][j-1]);
      dp[2][i][j]=dp[2][i][j-1]|dp[2][i+(1<<(j-1))][j-1];
      dp[3][i][j]=dp[3][i][j-1]&dp[3][i+(1<<(j-1))][j-1];
    }
  for(i=0;i<n;i++)
    for(j=0;j<30;j++)
      if(a[i]&(1<<j)){
        dp1[j][i]=i;
        dp2[j][i]=INF;
      }
      else{
        dp1[j][i]=INF;
        dp2[j][i]=i;
      }
  for(i=n-2;i>=0;i--)
    for(j=0;j<30;j++){
      dp1[j][i]=min(dp1[j][i],dp1[j][i+1]);
      dp2[j][i]=min(dp2[j][i],dp2[j][i+1]);
    }
  init(n);
  for(i=0;i<n;i++){
    for(j=s=0;j<30;j++){
      if(dp1[j][i]!=INF)
        b[s++]=dp1[j][i];
      if(dp2[j][i]!=INF)
        b[s++]=dp2[j][i];
    }
    sort_a(b,s,&ns);
    for(j=ns-1;j>=0;j--)
      if(get(i,b[j])>=k){
        if(j==ns-1)
          h=n-1;
        else
          h=b[j+1]-1;
        l=s=b[j];
        while(l<=h){
          m=(h+l)/2;
          if(get(i,m)>=k){
            s=m;
            l=m+1;
          }
          else
            h=m-1;
        }
        range_increment(i,s,s-i+1);
        break;
      }
  }
  for(i=0;i<n;i++)
    printf("%d\n",query(i));
  return 0;
}
int get(int l,int r){
  int a,b,c,d,len;
  len=map[r-l+1];
  a=max(dp[0][l][len],dp[0][r-(1<<len)+1][len]);
  b=min(dp[1][l][len],dp[1][r-(1<<len)+1][len]);
  c=dp[2][l][len]|dp[2][r-(1<<len)+1][len];
  d=dp[3][l][len]&dp[3][r-(1<<len)+1][len];
  return c-d-a+b;
}
int max(int x,int y){
  return (x>y)?x:y;
}
int min(int x,int y){
  return (x<y)?x:y;
}
void init( int n )
{
  N = 1;
  while( N < n ) N *= 2;
  int i;
  for( i = 1; i < N + n; i++ ) tree[i] = -1;
}
void range_increment( int i, int j, int val )
{
  for( i += N, j += N; i <= j; i = ( i + 1 ) / 2, j = ( j - 1 ) / 2 )
  {
    if( i % 2 == 1 ) tree[i] = max(val,tree[i]);
    if( j % 2 == 0 ) tree[j] = max(val,tree[j]);
  }
}
int query( int i )
{
  int ans = -1,j;
  for( j = i + N; j; j /= 2 ) ans = max(tree[j],ans);
  return ans;
}
void sort_a(int*a,int size,int*new_size){
  if (size < 2){
    (*new_size)=size;
    return;
  }
  int m = (size+1)/2,i;
  int *left,*right;
  left=(int*)malloc(m*sizeof(int));
  right=(int*)malloc((size-m)*sizeof(int));
  for(i=0;i<m;i++)
    left[i]=a[i];
  for(i=0;i<size-m;i++)
    right[i]=a[i+m];
  int new_l_size=0,new_r_size=0;
  sort_a(left,m,&new_l_size);
  sort_a(right,size-m,&new_r_size);
  merge(a,left,right,new_l_size,new_r_size,new_size);
  free(left);
  free(right);
  return;
}
void merge(int*a,int*left,int*right,int left_size, int right_size,int*new_size){
  int i = 0, j = 0,index=0;
  while (i < left_size|| j < right_size) {
    if (i == left_size) {
      a[index++] = right[j];
      j++;
    } else if (j == right_size) {
      a[index++] = left[i];
      i++;
    } else if (left[i] <= right[j]) {
      a[index++] = left[i];
      i++;
    } else {
      a[index++] = right[j];
      j++;
    }
    if(index>1&&a[index-2]==a[index-1])
      index--;
  }
  (*new_size)=index;
  return;
}








In Python3 :




import sys
def cost(a):
    x = 0
    y = 1
    for i in a:
        x |= i
        y &= i
    return((x-y)-(max(a)-min(a)))
    
def costlyIntervals(n, k, A):
    ans = []
    for m in range(n):
        cs = -1
        for i in range(0,n-1):
            for j in range(i,n):
                l = A[i:j+1]
                if A[m] in l:
                    x = cost(l)
                    if x >= k:
                        cs = max(cs,len(l))
        ans.append(cs)
    return(ans)
                        
    
    

if __name__ == "__main__":
    n, k = input().strip().split(' ')
    n, k = [int(n), int(k)]
    A = list(map(int, input().strip().split(' ')))
    result = costlyIntervals(n, k, A)
    print ("\n".join(map(str, result)))
                        








View More Similar Problems

Tree: Huffman Decoding

Huffman coding assigns variable length codewords to fixed length input characters based on their frequencies. More frequent characters are assigned shorter codewords and less frequent characters are assigned longer codewords. All edges along the path to a character contain a code digit. If they are on the left side of the tree, they will be a 0 (zero). If on the right, they'll be a 1 (one). Only t

View Solution →

Binary Search Tree : Lowest Common Ancestor

You are given pointer to the root of the binary search tree and two values v1 and v2. You need to return the lowest common ancestor (LCA) of v1 and v2 in the binary search tree. In the diagram above, the lowest common ancestor of the nodes 4 and 6 is the node 3. Node 3 is the lowest node which has nodes and as descendants. Function Description Complete the function lca in the editor b

View Solution →

Swap Nodes [Algo]

A binary tree is a tree which is characterized by one of the following properties: It can be empty (null). It contains a root node only. It contains a root node with a left subtree, a right subtree, or both. These subtrees are also binary trees. In-order traversal is performed as Traverse the left subtree. Visit root. Traverse the right subtree. For this in-order traversal, start from

View Solution →

Kitty's Calculations on a Tree

Kitty has a tree, T , consisting of n nodes where each node is uniquely labeled from 1 to n . Her friend Alex gave her q sets, where each set contains k distinct nodes. Kitty needs to calculate the following expression on each set: where: { u ,v } denotes an unordered pair of nodes belonging to the set. dist(u , v) denotes the number of edges on the unique (shortest) path between nodes a

View Solution →

Is This a Binary Search Tree?

For the purposes of this challenge, we define a binary tree to be a binary search tree with the following ordering requirements: The data value of every node in a node's left subtree is less than the data value of that node. The data value of every node in a node's right subtree is greater than the data value of that node. Given the root node of a binary tree, can you determine if it's also a

View Solution →

Square-Ten Tree

The square-ten tree decomposition of an array is defined as follows: The lowest () level of the square-ten tree consists of single array elements in their natural order. The level (starting from ) of the square-ten tree consists of subsequent array subsegments of length in their natural order. Thus, the level contains subsegments of length , the level contains subsegments of length , the

View Solution →