Блог пользователя eleganc

Автор eleganc, история, 17 месяцев назад, По-английски

Given an array of length n. The task is to make the sum of all the subarrays of length greater than two positive. To do this, you can replace any element with any integer x where -10^18 < x < 10^18. Find the minimum number of replacements needed to make the array positive.

Constraints: -10^9 < arr[i] < 10^9 and n < 10^5

Example:

Test Case 1: Arr = [-80 100 -80] Ans = 1

Test Case 2: Arr = [-10 19 -10 2] Ans = 1 (by making arr[2] = 10^18)

  • Проголосовать: нравится
  • +8
  • Проголосовать: не нравится

»
17 месяцев назад, # |
  Проголосовать: нравится -23 Проголосовать: не нравится
for(int i=2;i<=n;i++)
if(a[i-1]+a[i]<0){
ans++;
a[i]=10^18;
}
This should work
  • »
    »
    17 месяцев назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Your method fails on $$$a = [-2, 3, -2]$$$ as it doesn't take into account subarrays with length $$$> 2$$$.

»
17 месяцев назад, # |
  Проголосовать: нравится +3 Проголосовать: не нравится

sorry for my poor English

$$$10^5\times10^9<10^{18}$$$ so that means, we can separate the array to some segments by the position we choose to change. and for each subarrays of these segments, the sum must be positive.

we can search from the head of the array. it is obviously that the number we choose to change is better to be more backword. so we can use dp to maintain the segment.

»
17 месяцев назад, # |
Rev. 6   Проголосовать: нравится 0 Проголосовать: не нравится

Fact 1. It's always optimal to replace by $$$10^{18}$$$. Moreover, if you replace by this number, all arrays that contain this element will have $$$sum > 0$$$.

Fact 2. It's sufficient to check this condition on all subarrays of length 2 or 3. Proof. It can be shown that every integer $$$n > 1$$$ is representable as $$$n = 2x + 3y$$$ where $$$x, y \geq 0$$$ and $$$x$$$, $$$y$$$ are integers. So you can partition each subarray into subarrays of length 2 and 3 and if they have positive sum then the whole subarray will have positive sum.

Now you can use simple DP. Let $$$dp_{i, j}$$$ be the minimum number of replacements if we visited first $$$i$$$ elements and the last $$$10^{18}$$$ is on position $$$i - j$$$. This DP obviously have $$$O(n^2)$$$ states. So instead of keeping the actual position, let's keep $$$3$$$ instead if last $$$10^{18}$$$ is far away (position of it is less than $$$i - 2$$$). Transitions:

1) Replace next element by $$$10^{18}$$$. Then you should do $$$dp_{i + 1, 0} := min(dp_{i + 1, 0}, min(dp_{i, 0}, dp_{i, 1}, dp_{i, 2}, dp_{i, 3}))$$$.

2) Don't replace next element by anything. Then you should check if the condition on sum will be still satisfied and relax the DP.

  • »
    »
    17 месяцев назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Hi, I didn't understood your recurrence. Shouldn't it be dp(i+1, 0) = 1 + min {dp(i, j)} for j in [0, 3] since we are making a[i+1] infinity (10 ^ 18), the number of replacements is 1 + minimum possible replacement in a[1..i] as a[i+1] + a[i] + a[i-1] >= 0 and a[i+1] + a[i] >= 0.

    dp(i+1, 1) = dp(i, 0),,, dp(i+1, 2) = if a[i+1] + a[i] >= 0 then dp(i, 1) else min ( dp(i+1, 0), dp(i, 0) ),,, dp(i+1, 3) = if a[i+1] + a[i] >= 0 and a[i+1] + a[i] + a[i-1] >= 0 then dp(i, 3) else dp(i+1, 3) = /* not able to get this one */

  • »
    »
    17 месяцев назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Two queries:

    1) According to Fact 2, if I break the subarray into lengths of 2 and 3. Sum of consecutive elements of size 2 won't ensure sum of elements of size 3 greater than 0.

    Eg. [-80 100 -120 140] Breaking into size of 2 gives : [-80 100] & [-120 140]. But if you look at [-80 100 -120] then the sum is negative.

    2) If we store some value let's say INT_MAX in dp[]. Then shouldn't this expression be different:

    dp_{i+1,j} = min(dp_{i+1, j}, min(dp_{i, 0}, dp_{i, 1}, dp_{i, 2}, dp_{i, 3}))

    Why are you taking max of previous states if I am wrong?

    • »
      »
      »
      17 месяцев назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      1) I didn't say that it is sufficient to only check subarrays of length 2 (also you need to check subarrays of length 3).

      2) Fixed.

»
10 месяцев назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Can you think of any case which fails this ??

//Min number of operations to make array such that all subarrays of len>1 have sum >=0

#include<bits/stdc++.h>
using namespace std;

//-10^9 <= arr[i] <= 10^9
// 1<len(arr)<=10^5

//10^18
long long m = 100000000000000000;

int minOperations(vector<int> &arr)
{
    int n=arr.size();

    //Has no subarray of len>1
    if(n == 1) return 0;

    //Has only one subarray of len>1
    if(n == 2) return arr[0]+arr[1]<0;

    int cnt = 0;

    long long prev,curr,next;

    prev = m;
    curr = arr[0];
    next = arr[1];

    int ind = 1;

    //cout<<ind<<" "<<cnt<<endl;
    while(ind<n)
    {   
        if(prev+curr+next<0 || curr+next<0)
        {
            //set next as max, and in next iteration curr=next so 
            prev = curr;
            curr = m;
            cnt++;
        }else{
            prev = curr;
            curr = next;
        }

        //cout<<ind<<" "<<cnt<<endl;
        if(ind<n) next = arr[ind+1];
        ind++;
    }

    return cnt;
}

int main()
{
    //vector<int> arr = {2,5,-8,-1,2};
    //vector<int> arr = {-1,-1,-1,-1,-1};
    // vector<int>arr = {6,-5,5,10,-1,12};
    //vector<int>arr = {-2,3,-2};
    vector<int>arr = {-80,100,-120,140};
    cout<<minOperations(arr)<<endl;

}