Venkatesh2112001's blog

By Venkatesh2112001, history, 10 months ago, In English

For a given array A of size n, find the count of subarrays of size>=3, where the minimum of the elements at both the ends of subarray is greater than the maximum of all the numbers in between.

Formally, if the subarray starts at l and ends at r, then min(A[l], A[r]) > max(A[l+1], A[l+2],..., A[r-1]).

0<= n <=1e5 1<= A[i] <=1e9

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

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

I believe that size of subarray was >=3 and not >3 in the question,

my solution for >=3 was

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

.

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

    i feel we can do this in two for loops one forward and one reverse like for every i in forward for loop find the index of very next element whose value is greater than or equal to a[i] if it exists then do ans++; else do nothing now in reverse for loop for every element find the element whose value is greater than or equal to a[i] and whose index is less than given element if it exist then do ans++; also if the index where we got a element greater or equal to given element is equal to given element then do mul_count++; final ans=ans-mul_count;make sure to check the size if size is greater than 3 only add to ans

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

      yeah I did the same ig

      void solve() {
        int n;
        cin >> n;
        int a[n];
        for (int i = 0; i < n; ++i) {
          cin >> a[i];
        }
        int ans = 0;
        {
          stack<int> st;
          int cnt[n];
          for (int i = 0; i < n; i++) {
            cnt[i] = 1;
            while (!st.empty() and a[st.top()] < a[i]) {
              st.pop();
            }
            if (!st.empty() and i - st.top() >= 2) ans += cnt[st.top()], cnt[i] += cnt[st.top()];
            st.push(i);
          }
        }
        {
          stack<int> st;
          int cnt[n];
          for (int i = n - 1; i >= 0; i--) {
            cnt[i] = 1;
            while (!st.empty() and a[st.top()] <= a[i]) {
              st.pop();
            }
            if (!st.empty() and st.top() - i >= 2) ans += cnt[st.top()], cnt[i] += cnt[st.top()];
            st.push(i);
            // cout << ans << " ";
          }
        }
        cout << ans << endl;
        return;
      }
      
      • »
        »
        »
        »
        10 months ago, hide # ^ |
         
        Vote: I like it +1 Vote: I do not like it

        When n = 6 and arr = 4 3 1 2 3 5 The ans should be 3 but your code gives 4 as ans.

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

can you please explain the though process and how ?

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

This was the solution I came up with, but I am not sure if it's correct. My reasoning was that if we are at position a[i] we are only interested if we have bigger element both to the left and to the right, if that is so we can for sure form an offer (?). That way I preprocess the array so I have prefix and suffix arrays which are :

$$$prefix[i] = max(prefix[i-1], arr[i-1]$$$, and

$$$suffix[i] = max(suffix[i+1], arr[i+1])$$$

I do this, because at each local maximum the condition of having max both to the left and right will fail, and I will be able to "mark" ends. Now consecutive elements that have bigger elements both to the left and to the right form one offer, and every time I break that consecutive property I know I am out of that offer.

Examples I have come up with :

1 2 3 -> 0

5 1 2 3 4 -> 1

10 1 1 10 1 1 9 -> 2, now the last one is controversial, my code outputs 2, but we could debate what's the correct answer to it!

Anyways, here's my code :

#include <vector>
#include <iostream>
using namespace std;

void solve() {
    int n;
    cin >> n;
    vector<int> arr(n);
    for (int i = 0; i < n; i++) {
        cin >> arr[i];
    }

    vector<int> prefix(n);
    vector<int> suffix(n);

    int res = 0;

    for (int i = 1; i < n; i++) {
        prefix[i] = max(prefix[i-1], arr[i-1]);
        suffix[n-i-1] = max(suffix[n-i], arr[n-1]);
    }

    bool sw = false;
    for (int i = 0; i < n; i++) {
        if (arr[i] < suffix[i] && arr[i] < prefix[i] && sw == false) {
            sw = true;
            res++;
        }
        else if (!(arr[i] < suffix[i] && arr[i] < prefix[i]) && sw == true){
            sw = false;
        }
    }
    cout << res << endl;
}

int main() {
    int t;
    cin >> t;
    while (t--) solve();
}
  • »
    »
    10 months ago, hide # ^ |
     
    Vote: I like it 0 Vote: I do not like it

    Try n = 6 and arr = 4 3 1 2 3 5. The ans should be 3 i guess.

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

      can u check for any case for this code,since I earlier wrongly considered the equal case. Now it should work.

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

        n = 12 and arr = 10 19 7 10 6 17 1 10 7 12 14 8

        The correct output is 7 but your code gives 10 as ans

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

          // 19..10,17 // 10..17 // 17..10,12,14 // 10..12,14

          ain't the correct output 8?

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

            [10,7,12,14] is not valid as 10 < 12

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

              got it , I overcomplicated things :<

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

                Now it seems correct. You can try stress testing to check wheather there is any edge cases that might cause problem or not. It helps during contest to debug your wrong code

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

                  yeah, usually I either directly get the code or I get stuck on edge cases by overcomplicating ,nothing in between

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

First of all compresed value of array. each value is maximum n.

Now lets fix the maximum element of inside interval, for all i find maximum j < i such that a[j] > a[i] mark L[i], and find minimum j > i such that a[j] > a[i] mark this with R[i].

Now you know where is ith element is maximum.

Fix the ith, and you need to find how many l > L[i] ^ l < i and r < R[i] ^ r > i such that min(a[l], a[r]) > a[i].

lets consider : left block is interval (L[i], i) right block is interval (i, R[i]) A = how many number from left block such that > a[i] B = how many number from right block such that > a[i]

we are almost done. you only need to sum for all i, A * B.

to find A and B you can do offline fenwick tree, i think that is easier way to do that.

that is all.

correct me if i am wrong.

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

Can you check if this works?

UPD: This will only work if all the elements are unique.

void solve(int tc) {
    int n; cin >> n;
    vector<int> a(n);
    for(auto &i: a)
        cin >> i;
    int ans = 0;

    auto work = [&](){
        int mx = max(a[0], a[1]);
        for(int i = 2; i < n; i++){
            ans += (a[i] > a[i - 1]);
            ans -= (a[i] > mx);
            mx = max(mx, a[i]);
        }
    };

    work();
    reverse(a.begin(), a.end());
    work();

    cout << ans << '\n';
}
  • »
    »
    10 months ago, hide # ^ |
     
    Vote: I like it 0 Vote: I do not like it

    Your code gives wrong output when n = 6 and arr = 4 3 1 2 3 5. The ans is 3 but your code gives 4

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

      There shoud be 4 possible subarray.

      [1, 6], [2, 4], [2, 5], [2, 6]

      UPD: I assumed all elements will be unique. there will be double counting in my code for cases like this.

      a = [3, 1, 3]

      so, I fixed my code a bit.

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

        [2,6] subarray is not possible as min(a[2],a[6]) == max(a[3],a[4],a[5]) which violates the condition min(A[l], A[r]) > max(A[l+1], A[l+2],..., A[r-1]).

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

          Sorry, I missed that. I encountered a similar problem on a different blog earlier, which appeared in Amazon coding interview. It was mentioned that all elements are unique on that problem.

          For duplicate elements monotonic stack seems like the only option.

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

            RachitKansal's solution seems promising for this problem. He provided his solution in the first comment of this blog

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

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

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

it's just a simple stack q

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

#include <bits/stdc++.h> using namespace std; #define ll long long void prints(auto &vec) { for(auto it:vec) { cout<<it<<" "; } cout<<endl; } signed main() { ll t; cin>>t; while(t--) { ll n; cin>>n; vector<ll> v(n); for(ll i=0;i<n;i++) { cin>>v[i]; } stack<ll> st; st.push(v[0]); ll ans=0; for(ll i=2;i<n;i++) { while(!st.empty() && st.top()<v[i-1]) { st.pop(); } while(!st.empty() && min(st.top(),v[i])>v[i-1]) { if(st.top()>v[i]) { ans+=(int)st.size(); break; } else { ans+=1; st.pop(); } } st.push(v[i-1]); } cout<<ans<<endl; } return 0; }
»
10 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

Here is a straightforward solution in O(nlogn + nlogn) using sparse table and binary search (for subarray size >= 3):

code
»
10 months ago, hide # |
Rev. 2  
Vote: I like it 0 Vote: I do not like it
//<------------- !! GANPATI BAPPA MORYA !! ---------------->
#include<bits/stdc++.h>
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")

using namespace std;

typedef long long ll;
// #define int long long
//constexpr int INF = 1e18;
const int inf = 1e9;
#define pb push_back
#define eb emplace_back
#define pii pair<int,int>
#define vi vector<int>
#define vpi vector<pii>
#define all(a) (a).begin(), (a).end()
#define rall(a) (a).rbegin(), (a).rend()
#define sz(x) (int)(x).size()
#define ff first
#define ss second
#define yes() cout << "YES\n"
#define no() cout << "NO\n"
#define endl '\n'
#define d3(x,y,z) cout << x << " " << y << " " << z << "\n"
#define d2(x,y) cout << x << " " << y << "\n"
#define d(x) cout << x << "\n"
#define d0(x) cout << x << " "
#define bob() cout << "Bob\n"
#define alice cout << "Alice\n"
#define pb push_back

template<typename T>
istream& operator>>(istream &is, vector<T> &v)
{
    for (auto &x : v) is >> x;
    return is;
}
template<typename T>
ostream& operator<<(ostream &os, const vector<T> &v)
{
    for (auto &x : v) os << x << ' ';
    return os;
}


#ifndef judge
#define debug(x) ;
#else
#include "debug.h"
#endif

#define FOR(i, a, b) for(int i = (a); i < (b); ++i)
#define NFOR(i, a, b) for(int i = (b)-1; i >= (a); --i)
#define inp(v,n) for(int i = 0;i < n;++i) cin >> v[i];
#define rep(i,n) for(int i = 0;i < n;++i)
#define rep2(i,a,b) for(int i = (a);i < (b);++i)
#define rep3(i,a,b,x) for(int i = (a);i < (b);i += x)

constexpr int mod = 1e9 + 7;
constexpr int MOD = 998244353;

int nextGreater(const vector<int>& A, set<pair<int, int >> & ans, int revert = 0)
{
    int n = A.size();
    stack<int> st;
    int cnt = 0;

    for (int i = 0; i < n; ++i)
    {
        while (!st.empty() && A[i] >= A[st.top()])
        {
            if (abs(i - st.top()) >= 2)
            {
                int x = i;
                int y = st.top();
                if(x > y) swap(x, y);
                if(revert)
                {
                    x = n - i - 1;
                    y = n - st.top() - 1;
                    if(x > y) swap(x, y);
                    ans.insert({x, y});
                }
                else
                {
                    ans.insert({x, y});
                }
                cnt++;
            }
            st.pop();
        }
        st.push(i);
    }

    return cnt;
}

void Solve(int ts = 1)
{
    int n;
    cin >> n;
    vector<int> a(n);
    rep(i, n) cin >> a[i];
    vector<int>fused(n);
    vector<int>bused(n);
    set<pair<int, int >> ans;
    int nv = nextGreater(a, ans, 0);
    reverse(all(a));
    int pv = nextGreater(a, ans, 1);
    cout << ans.size() << "\n";
}
signed main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);

#ifdef judge
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    freopen("error.txt", "w", stderr);
#endif

    int _ = 1;
    // cin >> _;
    for(int __ = 1; __ <= _; ++__)
    {
        // cout << "CASE : " << __ << "\n";
        Solve(__);
    }
    return 0;
}
»
10 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

Use the max of the interval l..r as the pivot, then divide and conquer & use a monotone stack?